💂 对于封面:
Tower Bridge watercolor painting by Juan Bosco📚 摘录阐明:
本文摘自一本我在写作中的开源书《Istio & Envoy 底细》中 Envoy 申请与响应调度 一节。如果说你看到的转载图片不清,可回到原书。
-
申请与响应调度
- 相干组件
- 相干的监控指标
- Envoy 申请调度流程
- 申请与响应调度时序线
- 总结
- 一些乏味的扩大浏览
🎤 正式开编前。想说说写本节的一些故事原因。为何去钻研 Envoy 的申请与响应调度?
缘起于一个客户需要,须要对 Istio 网格节点故障疾速复原做一些调研。为此,我翻阅了大量的 Istio/Envoy 文档、大咖 Blog。看了很多很芜杂的信息:
- 衰弱检测
- 熔断
- Envoy 中的各个神秘又关系千头万绪的 timeout 配置
- 申请 Retry
TCP keepalive
、TCP_USER_TIMEOUT
配置
芜杂到最初,我不得不写个文章去梳理一下信息:Istio 网格节点故障疾速复原初探。但信息是梳理了,根底原理却没理顺。于是,我下决心去钻研一下 Envoy 的文档。是的,其实 Envoy 的文档曾经写得比拟粗疏。只是:
- 信息散落在一个个网页中,无奈用时序和流程的办法组织起来,形成一个有机的整体。
- 不去理解这个整体协作关系,只是一个一个参数离开来看,是无奈感性去衡量这些参数的。
- 指标与指标,指标与参数,关系简单
- 而下面的关系,都能够通过申请与响应调度流程串联起来
基于下面起因。我从文档、参数、指标推导出以下流程。<mark> 留神:临时未在代码中验证,请审慎参考。</mark>
申请与响应调度
实质上说,Envoy 就是一个代理。说起代理,第一反馈应该是有以下流程的软件 / 硬件:
- 接管来自
downstream
的Request
- 做一些逻辑,必要时批改
Request
,并断定upstream
目的地 - 转发(批改后)的
Request
到upstream
-
如果协定是一个
Request
&Reponse
式的协定(如 HTTP)- 代理通常会接管
upstream
的Response
- 做一些逻辑,必要时批改
Response
- 转发
Response
给downstream
- 代理通常会接管
确实,这也是 Envoy 代理 HTTP 协定的概要流程。但 Envoy 还要实现很多个性:
- 高效的
downstream
/upstream
传输 ➡️ 须要连贯复用
与连接池
- 灵便配置的转发指标服务策略 ➡️ 须要
Router
配置策略与实现逻辑 -
弹性服务 (resilient micro-services)
- 负载平衡
- 突发流量的削峰平谷 ➡️ 申请排队:pending request
- 应答异样 upstream、熔断器、爱护服务不雪崩 ➡️ 各种 timeout 配置、Health checking、Outlier detection、Circuit breaking
- 弹性重试 ➡️ retry
- 可察看性 ➡️ 无处不在的性能指标
- 动静编程配置接口 ➡️ xDS: EDS/LDS/…
要实现这些个性,申请与响应的流程天然不可能简略。
💡 看到这里,读者可能有疑难,本节的题目叫“申请与响应调度”?难度 Envoy 须要相似 Linux Kernel 调度线程一样,去调度解决 Request 吗?
对的,你说到点上了。
Envoy 利用了 事件驱动
设计模式。 事件驱动
的程序,绝对于 非事件驱动
的程序,能够用更少的线程,更灵便地管制在什么时候做什么工作,即更灵便的调度逻辑。且更绝的是:因为线程间共享的数据不多,线程的数据并发管制同时被大大简化。
在本节中,事件类型起码有:
- 内部的网络可读、可写、连贯敞开事件
-
各类定时器
- 重试定时
- 各种超时配置定时
因为应用了有限的申请调配到无限的线程的模式,加上申请可能须要重试,所以线程肯定要有一系列的逻辑,来“排序”什么申请应该先解决。什么申请因为 超时
或资源应用 超过配置下限
而应立即返回失败。
按本书的习惯,先上图。前面,对这个图一步步开展和阐明。
💡 互动图书:
- 倡议用 Draw.io 关上。图中蕴含大量的链接,链接到每一个组件、配置项、指标的文档阐明。
- 双屏,一屏看图,一屏看文档,是本书的正确浏览姿态。如果你在用手机看,那么,疏忽我吧 🤦
图:Envoy 申请与响应调度
用 Draw.io 关上
相干组件
上图是尝试阐明 Envoy 申请与响应调度
过程,以及串联相干的组件。其中能够看到一些组件:
- Listener – 应答 downstream 连贯申请
- HTTP Connection Manager(HCM) – HTTP 的外围组件,推动 http 流的读取、解释、路由(Router)
-
HCM-router – HTTP 路由外围组件,职责是:
- 断定 HTTP 下一跳的指标 cluster,即 upsteam cluster
- 重试
- Load balancing – upstream cluster 内的负载平衡
- pending request queue –
期待连接池可用连贯的申请队列
- requests bind to connection – 曾经调配到连贯的申请
- connection pool – worker 线程与 upstream host 专用的连接池
- health checker/Outlier detection – upsteam host 衰弱监督,发现异常 host 并隔离。
和一些 Circuit breaking(熔断开关)
下限条件:
- max_retries – 最大重试并发下限
- max_pending_requests –
pending request queue
的队列下限 - max_request – 最大并发申请数下限
- max_connections – upstream cluster 的最大连贯下限
须要留神的是,下面的参数是对于整个 upstream cluster 的,即是所有 worker thread、upstream host 汇总的下限。
相干的监控指标
咱们用相似驰名的 Utilization Saturation and Errors (USE) 方法学来分类指标。
资源过载形的指标:
- downstream_cx_overflow
- upstream_rq_retry_overflow
- upstream_rq_pending_overflow
- upstream_cx_overflow
资源饱和度指标:
- upstream_rq_pending_active
- upstream_rq_pending_total
- upstream_rq_active
谬误形的指标:
- upstream_rq_retry
- ejections_acive
- ejections_*
- ssl.connection_error
信息形的指标:
- upstream_cx_total
- upstream_cx_active
- upstream_cx_http*_total
因为图中曾经阐明了指标、组件、配置项的关系,这里就不再文字叙述了。图中也提供了到指标文档和相干配置的链接。
Envoy 申请调度流程
先说说申请组件流转局部,流程图能够从相干的文档推理为(未齐全验证,存在局部推理):
图:Envoy 申请调度流程图
用 Draw.io 关上
申请与响应调度时序线
本节结尾说了,写本节的间接原因是: 须要对 Istio 网格节点故障疾速复原做一些调研。疾速复原
的前提是:
- 对曾经发送到
故障 upstream host
或绑定到故障 upstream host
的申请,疾速响应失败 - 用
Outlier detection / health checker
辨认出故障 upstream host
,并把它移出负载平衡列表
所有问题都依赖于一个问题:如何定义和发现 upstream host
出了故障?
-
网络分区或对端解体或负载过高
- 大多数状况下,分布式系统只能通过超时来发现这种问题。所以,要发现
故障 upstream host
或故障 request
,须要配置
- 大多数状况下,分布式系统只能通过超时来发现这种问题。所以,要发现
-
对端有响应,L7 层的失败(如 HTTP 500),或 L3 层的失败(如 TCP REST/No router to destination/ICMP error)
- 这是能够疾速发现的失败
对于 网络分区或对端解体或负载过高
,须要 timeout 发现的状况,Envoy 提供了丰盛的 timeout 配置。丰盛到有时让人不晓得应该用哪个才是正当的。甚至配置一不小心,就配置出一些逻辑上长短与实现设计矛盾的值。所以,我尝试用理分明 申请与响应调度时序线
,而后看相干 timeout 配置关联到这个工夫线的哪个点,那么整个逻辑就分明了。配置也更容易合理化了。
下图是申请与响应的时序线,以及相干的 timeout 配置与产生的指标,以及它们的分割。
图:Envoy 申请与响应时序线
用 Draw.io 关上
简略阐明一下工夫线:
- 如果 downstream 复用了之前的连贯,能够跳过 2 & 3
- downstream 发动 新连贯(TCP 握手)
- TLS 握手
- Envoy 接管 downstream request header & body
- Envoy 执行路由 (Router) 规定,断定下一跳的 upstream cluster
- Envoy 执行 Load Balancing 算法,断定下一跳的 upstream cluster 的 upstream host
- 如果 Envoy 曾经有闲暇连贯到 upstream host,则跳过 8 & 9
- Envoy 向 upstream host 发动新连贯(TCP 握手)
- Envoy 向 upstream host 发动 TLS 握手
- Envoy 向 upstream host 转发送 requst header & body
- Envoy 接管 upstream host 响应的 response header & body
- upstream host 连贯开始 idle
- Envoy 向 downstream 转发送 response header & body
- downstream host 连贯开始 idle
相应地,图中也标注了相干超时配置与工夫线步骤的关系,从开始计时顺序排列如下
- max_connection_duration
-
transport_socket_connect_timeout
- 指标
listener.downstream_cx_transport_socket_connect_timeout
- 指标
- request_headers_timeout
- requst_timeout
-
Envoy 的 route.timeout 即 Istio 的
Istio request timeout(outbound)
留神,这个超时值是把 申请解决时理论的 retry 的总工夫也算上的。
- 指标
cluster.upstream_rq_timeout
- 指标
vhost.vcluster.upstream_rq_timeout
- 指标
- max_connection_duration
-
connection_timeout
- 指标
upstream_cx_connect_timeout
- 指标
- transport_socket_connect_timeout
- httpprotocoloptions.idle_timeout
总结
想要 Envoy 在压力与异常情况下,有个比拟合乎预期的体现,须要给 Envoy 一些正当于具体应用环境与场景的配置。而要配置好这堆参数的前提,是对相干解决流程与逻辑的洞察。下面把 申请与响应调度
与 申请与响应调度时序线
都过了一遍。心愿对理解这些方面有肯定的帮忙。
不只是 Envoy,其实所有做代理的中间件,可能最外围的货色都在这一块了。所以,不要冀望一下把常识齐全吃透。这里,也只是心愿让读者在这些流程上,有一个线索,而后通过线索去学习,方可不迷失方向。
一些乏味的扩大浏览
- https://www.istioworkshop.io/…
- https://tech.olx.com/demystif…