1. 区域感知路由

通常,始发集群和上游集群属于不同区域的部署中,Envoy执行区域感知路由

区域感知路由(zone aware routing)用于尽可能地向上游集群中的本地区域发送流量,并大致确保将流量
均衡分配至上游相关的所有端点;它依赖于以下几个先决条件
- 始发集群(客户端)和上游集群(服务端)都未处于恐慌模式
- 启用了区域感知路由
- 始发集群与上游集群具有相同数量的区域
- 上游集群具有能承载所有请求流量的主机

Envoy将流量路由到本地区域,还是进行跨区域路由取决于始发集群和上游集群中健康主机的百分比
- 始发集群的本地区域百分比大于上游集群中本地区域的百分比:Envoy 计算可以直接路由到上游集群的本地区域的
请求的百分比,其余的请求被路由到其它区域

  • 始发集群本地区域百分比小于上游集群中的本地区域百分比:可实现所有请求的本地区域路由,并可承载一部分其
    它区域的跨区域路由

区域感知路由仅支持0优先级

2. 熔断

多级服务调度用场景中,某上游因网络 故障或服务繁忙无法响应请求时很可能会导致多级上游调用者大规模联故障,进而导致整个系统不可用,此即为服务的雪崩效应;

  • 服务雪崩效应是一种因“提供者”的不可用导致“服务消费者”的,并将不可用逐渐放大的过程

服务网格之上的微服务应用中,多级调用的长调用链并不鲜见.

熔断:上游服务(被调用者,即服务提供者)因压力过大而变得响应过慢甚至失败时,下游服务(服务消费者)通过暂时切断对上游的请求调用达到牺牲局部,保全上游甚至整体的目的

  • 熔断打开 ( Open):在固定时间窗口内,检测到的失败指标达到指定的阈值时启动熔断

  • 熔断半打开 (Half Open):断路器在工作一段时间后自动切换至半打开状态,并根据下一次请求的返回结果判定状态切换

    • 请求成功:转为熔断关闭状态
    • 请求失败:切回熔断打开状态
  • 熔断关闭 ( Closed):一定时长后上游服务可能会变得再次可用,此时下游即可关闭熔断,并再次请求其服务

总结起来, 熔断 是分布式 应用常的一种流量管理模式,它能够让应用程序免受上游服务失败、延迟峰值或
其它网络异常的侵害

Envoy在网络级别强制进行断路限,于是不必独立配置和编码每个应用

2.1 Envoy断路器

Envoy支持多种类型的完全分布式断路机制,达到由其定义的阈值时,相应的断路器即会溢出:
1. 集群最大连接数: Envoy 同上游集群建立的最大连接数,仅适用于HTTP/1.1,因为 HTTP/2可以链路复用
1. 集群最大请求数:在给定的时间,中所有主机未完成仅适用于 HTTP/2
1. 集群可挂起的最大请求数: 连接池满载时允许的等待队列的最大长度
1. 集群最大活跃并发重试次数: 给定时间内集群中所有主机可以执行的最大并发重试次数
1. 集群最大并发连接池: 可以同时实例化出最大连接池数量

每个断路器都可在集群及优先级的基础上进行配置和跟踪,它们可分别拥有各自不同的设定

在Istio中,熔断的功能通过连接池(连接池管理)和故障实例隔离(异常点检测)进行定义,而Envoy的断路器通常仅对应于Istio中的连接池功能

  • 通过限制某个客户端对目标服务的连接数,访问请求,队列长度和重试次数等,避免对一个服务的过量访问
  • 某个服务实例频繁超时或出错时将其逐出,以避免影响整个服务

2.2 连接池和熔断器

连接池的常用指标:

  1. 最大连接数: 表示在任何给定时间内,Envoy与上游集群建立的最大连接数,适用于http/1.1
  2. 每连接最大请求数: 表示在任何给定时间内,上游集群中所有主机可以处理的最大请求数,若设为1则会禁止keepalive特性
  3. 最大请求重试次数: 在指定时间内对目标主机最大重试次数
  4. 连接超时时间: TCP连接超时时间,最小值必须大于1ms,最大连接数和连接超时时间对TCP和HTTP都有效的通用连接设置
  5. 最大等待请求数:待处理请求队列的长度,若该断路器溢出,集群的upstream_rq_pending_overflow计数器就会递增

熔断器的常用指标(Istio上下文)

  1. 连续错误响应个数: 在连续一个检查周期内,连续出现5xx错误的个数.
  2. 检查周期: 将会对检查周期内的响应码进行筛选
  3. 隔离实例比例: 上游实例中,允许倍隔离的最大比例
  4. 最短隔离时间: 实例第一次被隔离的时间,之后每次隔离时间为隔离次数与最短隔离时间的乘积
---
clusters:
- name: ...
...
connect_timeout: ... # TCP连接的超时时长,即主机网络连接超时,合理的设置可以能够改善因调用服务变慢而导致整个链接变慢的情形;
max_requests_per_connection: ... # 每个连接可以承载的最大请求数,HTTP/1.1和HTTP/2的连接池均受限于此设置,无设置则无限制,1表示禁用keep-alive
...
circuit_breakers: {...} # 熔断相关的配置,可选;
threasholds: [] # 适用于特定路由优先级的相关指标及阈值的列表;
- priority: ... # 当前断路器适用的路由优先级;
max_connections: ... # 可发往上游集群的最大并发连接数,仅适用于HTTP/1,默认为1024;超过指定数量的连接则将其短路;
max_pending_requests: ... # 允许请求服务时的可挂起的最大请求数,默认为1024;;超过指定数量的连接则将其短路;
max_requests: ... # Envoy可调度给上游集群的最大并发请求数,默认为1024;仅适用于HTTP/2
max_retries: ... # 允许发往上游集群的最大并发重试数量(假设配置了retry_policy),默认为3;
track_remaining: ... # 其值为true时表示将公布统计数据以显示断路器打开前所剩余的资源数量;默认为false;
max_connection_pools: ... # 每个集群可同时打开的最大连接池数量,默认为无限制;

使用fortio进行测试

fortio load -c 2 -qps 0 -n 20 -loglevel Warning URL

-c 2 并发连接个数
-qps 0 不做限制
-n 20 发20个请求
-loglevel Warning log的等级为Warning

3. 熔断测试

3.1 docker-compose

共11个container:

  • envoy:Front Proxy,地址为172.31.35.2
  • webserver01:第一个后端服务
  • webserver01-sidecar:第一个后端服务的Sidecar Proxy,地址为172.31.35.11, 别名为red和webservice1
  • webserver02:第二个后端服务
  • webserver02-sidecar:第一个后端服务的Sidecar Proxy,地址为172.31.35.12, 别名为blue和webservice1
  • webserver03:第三个后端服务
  • webserver03-sidecar:第一个后端服务的Sidecar Proxy,地址为172.31.35.13, 别名为green和webservice1
  • webserver04:第四个后端服务
  • webserver04-sidecar:第四个后端服务的Sidecar Proxy,地址为172.31.35.14, 别名为gray和webservice2
  • webserver05:第五个后端服务
  • webserver05-sidecar:第五个后端服务的Sidecar Proxy,地址为172.31.35.15, 别名为black和webservice2
version: '3'services:front-envoy:image: envoyproxy/envoy-alpine:v1.21.5volumes:- ./front-envoy.yaml:/etc/envoy/envoy.yamlnetworks:- envoymeshexpose:# Expose ports 80 (for general traffic) and 9901 (for the admin server)- "80"- "9901"webserver01-sidecar:image: envoyproxy/envoy-alpine:v1.21.5volumes:- ./envoy-sidecar-proxy.yaml:/etc/envoy/envoy.yamlhostname: rednetworks:envoymesh:ipv4_address: 172.31.35.11aliases:- webservice1- redwebserver01:image: ikubernetes/demoapp:v1.0environment:- PORT=8080- HOST=127.0.0.1network_mode: "service:webserver01-sidecar"depends_on:- webserver01-sidecarwebserver02-sidecar:image: envoyproxy/envoy-alpine:v1.21.5volumes:- ./envoy-sidecar-proxy.yaml:/etc/envoy/envoy.yamlhostname: bluenetworks:envoymesh:ipv4_address: 172.31.35.12aliases:- webservice1- bluewebserver02:image: ikubernetes/demoapp:v1.0environment:- PORT=8080- HOST=127.0.0.1network_mode: "service:webserver02-sidecar"depends_on:- webserver02-sidecarwebserver03-sidecar:image: envoyproxy/envoy-alpine:v1.21.5volumes:- ./envoy-sidecar-proxy.yaml:/etc/envoy/envoy.yamlhostname: greennetworks:envoymesh:ipv4_address: 172.31.35.13aliases:- webservice1- greenwebserver03:image: ikubernetes/demoapp:v1.0environment:- PORT=8080- HOST=127.0.0.1network_mode: "service:webserver03-sidecar"depends_on:- webserver03-sidecarwebserver04-sidecar:image: envoyproxy/envoy-alpine:v1.21.5volumes:- ./envoy-sidecar-proxy.yaml:/etc/envoy/envoy.yamlhostname: graynetworks:envoymesh:ipv4_address: 172.31.35.14aliases:- webservice2- graywebserver04:image: ikubernetes/demoapp:v1.0environment:- PORT=8080- HOST=127.0.0.1network_mode: "service:webserver04-sidecar"depends_on:- webserver04-sidecarwebserver05-sidecar:image: envoyproxy/envoy-alpine:v1.21.5volumes:- ./envoy-sidecar-proxy.yaml:/etc/envoy/envoy.yamlhostname: blacknetworks:envoymesh:ipv4_address: 172.31.35.15aliases:- webservice2- blackwebserver05:image: ikubernetes/demoapp:v1.0environment:- PORT=8080- HOST=127.0.0.1network_mode: "service:webserver05-sidecar"depends_on:- webserver05-sidecarnetworks:envoymesh:driver: bridgeipam:config:- subnet: 172.31.35.0/24

3.2 envoy.yaml

熔断: 最大并发连接数 1,最大挂起连接数1,最大并发重试数3

异常检测: 时间间隔1S,连续5xx错误3个,网关故障3次,被弹出基准时长10s,因网关故障被弹出主机的百分比100%,集群中最多被弹出30%的主机,集群启动成功率异常检测最少主机数2

admin:access_log_path: "/dev/null"address:socket_address: { address: 0.0.0.0, port_value: 9901 }static_resources:listeners:- address:socket_address: { address: 0.0.0.0, port_value: 80 }name: listener_httpfilter_chains:- filters:- name: envoy.filters.network.http_connection_managertyped_config:"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManagercodec_type: autostat_prefix: ingress_httproute_config:name: local_routevirtual_hosts:- name: backenddomains:- "*"routes:- match:prefix: "/livez"route:cluster: webcluster2- match:prefix: "/"route:cluster: webcluster1http_filters:- name: envoy.filters.http.routerclusters:- name: webcluster1connect_timeout: 0.25stype: STRICT_DNSlb_policy: ROUND_ROBINload_assignment:cluster_name: webcluster1endpoints:- lb_endpoints:- endpoint:address:socket_address:address: webservice1port_value: 80circuit_breakers:thresholds:         max_connections: 1max_pending_requests: 1max_retries: 3- name: webcluster2connect_timeout: 0.25stype: STRICT_DNSlb_policy: ROUND_ROBINload_assignment:cluster_name: webcluster2endpoints:- lb_endpoints:- endpoint:address:socket_address:address: webservice2port_value: 80outlier_detection:interval: "1s"consecutive_5xx: "3"consecutive_gateway_failure: "3"base_ejection_time: "10s"enforcing_consecutive_gateway_failure: "100"max_ejection_percent: "30"success_rate_minimum_hosts: "2"

3.3 熔断部署测试

# docker-compose up
## 测试脚本
# cat send-requests.sh
#!/bin/bash
if [ $# -ne 2 ]
thenecho "USAGE: $0 <URL> <COUNT>"exit 1;
fi
URL=$1
COUNT=$2
c=1
#interval="0.2"
while [[ ${c} -le ${COUNT} ]];
do#echo "Sending GET request: ${URL}"curl -o /dev/null -w '%{http_code}\n' -s ${URL} &(( c++ ))
#  sleep $interval
done
wait

测试效果

/(webcluster1)大概会有5.83%的几率503(11.12.13三台)
/livez(webcluster2)大概有8.83%的记录503(14.15两台)

# ./send-requests.sh http://172.31.35.2/ 600 > scale.txt
# wc -l scale.txt
600 scale.txt
# grep 200 scale.txt|wc -l
565
# grep 5 scale.txt|wc -l
35
# echo 'scale=4;35/600*100'|bc
5.8300
# ./send-requests.sh http://172.31.35.2/livez 600 > livez.txt
# grep 503 livez.txt|wc -l
53
# echo 'scale=4;53/600*100'|bc
8.8300

如果此时将13服务器状态置fail和之前几乎没区别

root@k8s-node-1:~# curl -XPOST -d 'livez=FAIL' http://172.31.35.13/livez
root@k8s-node-1:~# curl http://172.31.35.13/livez
FAILroot@k8s-node-1:~# ^C
root@k8s-node-1:~# curl http://172.31.35.13/livez
FAIL
## 此时
# ./send-requests.sh http://172.31.35.2/ 600 > scale.txt
# grep 503 scale.txt|wc -l
44
# echo 'scale=4;30/600*100'|bc
5.0000

将15服务器状态改为FAIL,503的返回几乎是之前的4倍

root@k8s-node-1:~curl -XPOST -d 'livez=FAIL' http://172.31.35.15/livez
root@k8s-node-1:~# curl http://172.31.35.15/livez
FAILroot@k8s-node-1:~#
# ./send-requests.sh http://172.31.35.2/livez 600 > livez.txt
# grep 5 livez.txt|wc -l
142
# echo 'scale=4;142/600*100'|bc
23.6600

【云原生 | Kubernetes 系列】--Envoy熔断相关推荐

  1. 【云原生 | Kubernetes 系列】---Skywalking部署和监控

    [云原生 | Kubernetes 系列]-Skywalking部署和监控 1. 分布式链路追踪概念 在较大的web集群和微服务环境中,客户端的一次请求可能需要经过多个不同的模块,多个不同中间件,多个 ...

  2. 【云原生Kubernetes系列第五篇】kubeadm v1.20 部署K8S 集群架构(人生这道选择题,总会有遗憾)

    系列文章目录 ??即日起,更新云原生相关知识,喜欢的小伙伴可以给我点个三连喔 ??收录至专栏 云原生 ??[云原生Docker系列第一篇]Docker镜像管理 ??[云原生Docker系列第二篇]Do ...

  3. 【云原生 | Kubernetes 系列】--持续交付和持续部署GITOPS(上)

    1. 持续交付和持续部署 Continuous Integration Continuous Delivery Continuous Deployment Plan Code Build Test R ...

  4. 【云原生 | Kubernetes 系列】1个POD2个container实现Wordpress K8s部署

    1. Wordpress架构 2. 构建wordpress镜像 2.1 构建nginx-base-wordpress镜像 Dockerfile FROM harbor.intra.com/baseim ...

  5. 【云原生 | Kubernetes 系列】----污点与容忍

    污点与容忍 污点(taints),用于node节点排斥Pod调度.与亲和效果相反.即taint的node排斥Pod的创建. 容忍(toleration),用于Pod容忍Node节点的污点信息.即nod ...

  6. 【云原生 | Kubernetes 系列】K8s 实战 管理 Secret 详解

    kubectl 管理 Secret 前言 一.使用 kubectl 管理 Secret 1.1.创建 Secret 1.2.验证 Secret 1.3.解码 Secret 1.4.清理 二.使用配置文 ...

  7. 【云原生 | Kubernetes 系列】K8s 实战 一文学会如何从 PodSecurityPolicy 迁移到内置的 PodSecurity 准入控制器

    PodSecurityPolicy 迁移到内置的 PodSecurity 准入控制器 前言 一.Pod 安全性 二.访问权限 三.标准化 PodSecurityPolicy 3.1.去掉纯粹变更性质的 ...

  8. 【云原生 | Kubernetes 系列】--Gitops持续交付 Tekton Pipeline使用进阶(pvc和Results)

    Tekton Pipeline使用进阶 1. 基于Maven项目构建 主要实现source to package的过程 包含2个Task: fetch-from-source和build 使用pvc实 ...

  9. 【云原生 | Kubernetes 系列】--Gitops持续交付和持续Tekton Triggers

    Tekton Triggers Tekton 几个项目 Tekton Pipelines Task Steps:执行具体操作,在容器中执行的命令或脚本 command script TaskRun 运 ...

最新文章

  1. (转)uml 静态视图依赖
  2. CSS3蓝色宽屏二级下拉菜单DEMO演示
  3. Java自带的性能监测工具之jinfo
  4. 修改数据结构记录,将同级数据改成父子集数据
  5. Android通过意图使用内置的音频播放器
  6. 自定义input[type=file]的兼容样式
  7. jvm(13)-线程安全与锁优化
  8. CSS深入理解vertical-align和line-height的基友关系
  9. jdk,Eclipse,SWTDesigner安装【原创】
  10. docker entrypoint入口文件详解
  11. 读保护_GD32VF103之片上flash读、写、擦除
  12. Linux定时器:无节拍机制tickless(CONFIG_NO_HZ)
  13. springboot jar包运行中获取资源文件
  14. Python 学习 DAY1
  15. pandas.to_numeric
  16. 艺工交叉——观《达芬奇的人生密码》有感
  17. lua——牛牛牌型处理相关算法(下)——牌型比较
  18. pytorch创建新环境
  19. jupyter notebook 常用魔法函数 Magic Function%time %timeit %who %pip %cd
  20. linux软中断和消息队列结合,传统UNIX进程间通信内核实现概要

热门文章

  1. Jmeter分布式压测介绍、原理及实操(一台master-windows控制机,三台slaves-linux负载机)
  2. [NCTF2019]Fake XML cookbook 1
  3. Linux socket编程
  4. C语言:srand函数与rand函数的使用(纯干货)【易懂】
  5. ppt在线快速转换成pdf的方法
  6. 组图:码头上的搬运工
  7. 【转】SpringMVC的工作原理图
  8. CAD制图初学入门技巧:如何批量生成CAD填充边界?
  9. android HorizontalScrollView讲解
  10. 自动控制原理笔记-频率响应法-频率特性的概念