天天看点

Envoy 上游集群断路器

雪崩效应

  • 多级服务调度用场景中,某上游服务因网络故障或服务繁忙无法响应请求时很可能会导致多级上游调用者大规模级联故障,进而导致整个系统不可用,此即为服务的雪崩效应;
  • 服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程;
  • 服务网格之上的微服务应用中,多级调用的长调用链并不鲜见;

熔断

  • 熔断:上游服务(被调用者,即服务提供者)因压力过大而变得响应过慢甚至失败时,下游服务(服务消费者)通过暂时切断对上游的请求调用达到牺牲局部,保全上游甚至是整体之目的;
  • 熔断打开(Open):在固定时间窗口内,检测到的失败指标达到指定的阈值时启动熔断;
  • 所有请求会直接失败而不再发往后端端点;
  • 熔断半打开(Half Open):断路器在工作一段时间后自动切换至半打开状态,并根据下一次请求的返回结果判定状态切换;
  • 请求成功:转为熔断关闭状态;
  • 请求失败:切回熔断打开状态;
  • 熔断关闭(Closed):一定时长后上游服务可能会变得再次可用,此时下游即可关闭熔断,并再次请求其服务;
  • 总结起来, 熔断是分布式应用常用的一种流量管理模式,它能够让应用程序免受上游服务失败、延迟峰值或其它网络异常的侵害;
  • Envoy在网络级别强制进行断路限制,于是不必独立配置和编码每个应用;
Envoy 上游集群断路器

Envoy断路器

  • Envoy支持多种类型的完全分布式断路机制,达到由其定义的阈值时,相应的断路器即会溢出:
  • 集群最大连接数:Envoy同上游集群建立的最大连接数。如果此断路器溢出,集群的upstream_cx_overflow计数器将增加。cluster maximum connections + (number of endpoints in a cluster) * (connection pools for the cluster);
  • 集群最大请求数:在任何给定时间,集群中所有主机的最大请求数。如果此断路器溢出,集群的upstream_rq_pending_overflow
  • 集群可挂起的最大请求数:在等待连接池连接就绪时将排队的最大请求数。每当没有足够的上游连接可用以立即分派请求时,请求就会添加到待处理请求列表中。对于 HTTP/2 连接,如果未配置最大并发流 和每个连接的最大请求数,则所有请求将在同一连接上多路复用,因此只有在尚未建立连接时才会触发此断路器。如果此断路器溢出,集群的 upstream_rq_pending_overflow计数器将增加。对于 HTTP/3,相当于 HTTP/2 的最大并发流是最大并发流。
  • 集群最大活动并发重试次数:在任何给定时间,集群中所有主机可以进行的最大重试次数。一般来说,我们建议使用重试预算;但是,如果首选静态断路,则应积极断路重试。这样可以允许对偶发性故障进行重试,但整体重试量不会爆炸并导致大规模级联故障。如果此断路器溢出,则集群的 upstream_rq_retry_overflow计数器将增加。
  • 集群最大并发连接池:可以同时实例化的最大连接池数。
  • 每个断路器都可在每个集群及每个优先级的基础上进行配置和跟踪,它们可分别拥有各自不同的设定;
  • 注意:在Istio中,熔断的功能通过连接池(连接池管理)和故障实例隔离(异常点检测)进行定义,而Envoy的断路器通常仅对应于Istio中的连接池功能;
  • 通过限制某个客户端对目标服务的连接数、访问请求、队列长度和重试次数等,避免对一个服务的过量访问;
  • 某个服务实例频繁超时或者出错时交其昨时逐出,以避免影响整个服务;

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

  • 连续错误响应个数:在一个检查周期内,连续出现5xx错误的个数,例502、503状态码;
  • 检查周期:将会对检查周期内的响应码进行筛选;
  • 隔离实例比例:上游实例中,允许被隔离的最大比例;采用向上取整机制,假设有10个实例,13%则最多会隔离2个实例;
  • 最短隔离时间:实例第一次被隔离的时间,之后每次隔离时间为隔离次数与最短隔离时间的乘积;

断路器配置格式

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: ... # 每个集群可同时打开的最大连接池数量,默认为无限制;
    retry_budget: ...         # 指定与活动请求数相关的并发重试限制。此参数是可选的。
      budget_percent: ...     
        value: ...          # 将并发重试限制指定为活动请求和活动挂起请求总和的百分比。例如,如果有 100 个活动请求并且budget_percent 设置为 25,则可能有 25 次活动重试。此参数是可选的。默认为 20%。  
      min_retry_concurrency: ...   # 指定重试预算允许的最小重试并发。活动重试次数的限制可能永远不会低于此数量。此参数是可选的。默认为 3。
  per_host_thresholds:   # 适用于集群中每个单独主机的可选每主机限制。当前,每个主机的限制仅支持max_connections字段。      

断路器配置示例

查看代码

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_http
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains:
              - "*"
              routes:
              - match:
                  prefix: "/livez"
                route:
                  cluster: webcluster2
              - match:
                  prefix: "/"
                route:
                  cluster: webcluster1
          http_filters:
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
  - name: webcluster1
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: webcluster1
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: webservice1
                port_value: 80
    circuit_breakers:
      thresholds:         
        max_connections: 1
        max_pending_requests: 1
        max_retries: 3

  - name: webcluster2
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: webcluster2
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: webservice2
                port_value: 80
    outlier_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"      

微服务环境压测工具

  • 工具介绍
  • ​​https://github.com/fortio/fortio​​
  • fortio load -c 2 -qps 0 -n 20 -loglevel Warning URL

参考文档

​​https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/circuit_breaking​​

继续阅读