Skip to content

第6章 分布式流量防护——基于Sentinel

流量防护是确保分布式系统高可用的关键手段之一。对应用做好流量防护(尤其是在复杂的调用链路关系中),能够减少很多线上故障。

Sentinel 是主流的分布式系统的高可用流量防护组件之一。本章将介绍如何利用 Sentinel对应用进行高可用的流量防护。

6.1 认识分布式流量防护

在分布式系统中,服务之间的相互调用会生成分布式流量。如何通过组件进行流量防护,并有 效控制流量,是分布式系统的技术挑战之一。

6.1.1 什么是分布式流量防护

在分布式系统中,一次 RPC 请求过程如图 6-1 所示。下面结合 RPC 请求,来分析流量防护组件在分布式系统中的角色:

  • 请求被流量防护组件处理后,被路由到交易服务(见图 6-1中的左侧)。
  • 请求被交易服务处理完后,调用订单服务。周理,请求也会先被流防护组件处理,再被路由到订单服务。
  • 请求被订单服务处理完后,调用商品服务。同理,请求也会先被流防护组件处理,再被商品服务处理。

从分层架构的角度,可以将流量防护分为:前置式流量防护和嵌入式流量防护。

1.前置式流量防护

如图 6-2所示,在分层架构中,前置流量防护组件处于应用和负载均衡组件之前。可以在前置流量防护组件中添加流量防护的路由策略,使得流量还没有被路由到应用就先被前置流量防护组件有效地防护起来。常见的前置流量防护组件有:Spring Cloud Gateway、Zuul 等路由网关。

有些开发人员会将业务逻辑(比如安全校验)放在负载均衡中。为了起到有效的流护作用,可以在前置式流量防护组件之前增加 DNS 的流量防护,真正做到前置式流量防护。

前置式流量防护具备如下优势:

  • 对应用是零侵入的。
  • 流量防护策略比较简单,不会给业务开发人员带来更多的技术成本。
  • 开发人员能够非常方便地开启和关闭流量防护,而应用是无感知的。

2.嵌入式流量防护

如图 6-3 所示,在分层架构中,嵌入式流量防护组件被内嵌到应用A和应用B中。应用需要依赖流量防护组件完成流量防护。

嵌入式流量防护组件通常都会和应用强耦合,但可以采用动态的全局开关做到流量防护功能的自动上下线。

嵌入式流量防护具备如下优势:

  • 应用可以动态地调整流量防护策略
  • 流量防护的覆盖范围更广,可以从应用中的实例到应用中的任意代码块。
  • 流量防护更加有效。

从图 6-3 中可以看出,在正常的流量请求到达应用 A 和应用 B 之前,嵌入式流量防护组件不会生效。

6.1.2 为什么需要分布式流量防护

在分布式系统中,服务被部署在不同的服务进程中,服务之间通过 RPC 通信完成服务请求。

一次核心的业务请求通常需要调用几十个服务,从而产生上百次 RPC 请求。熟悉分布式系统的开发人员都知道,“网络抖动”会直接影响 RPC 请求的稳定性。

在分布式系统中,数据从服务A发送到服务B需要一段延迟时间,延迟时间由传输时间和处理时间组成。

通常“网络抖动”是指,数据从服务 A 传输到服务 B 的最大延迟时间和最小延迟时间之间的时间差。比如,最大延迟时间为20ms,最小延迟时间为5ms,那么“网络抖动”就是15ms。“网络抖动”是衡量网络是否稳定的一个标志,“网络抖动”越大,网络越不稳定。

图 6-4描述了电商领域中的交易服务、商品服务、订单服务、支付服务、库存服务、供应链服务、进销存货服务、仓库服务和物流服务之间的调用链路关系。

服务之间的调用链路关系介绍如下:

(1) 用户发起订单交易请求,交易请求会先后调用交易服务、商品服务、订单服务等9个服务。

(2) 在处理交易请求的过程中,会出现调用链路长、跨服务调用次数多的现象,从而导致RPC请求的次数增多,增加了服务调用不可用的可能性。

(3) 如果某一个服务不规范,则需要将服务调用的网络超时时间设置得很长,比如 30s。如果出现超时异常,则这个服务在 30s 内只能处理这一个请求,严重地降低了服务的 QPS 和 TPS。

(4) 如果在某一次的电商促销活动中(比如“双十一”),上百万个用户同时发起交易请求形成了请求流量的“洪峰”,这时的请求流量是非“双十一”时间段的几十倍,此时支付服务集群中的某一个实例在处理大流量的支付请求的过程中出现了服务不可用的故障,若出现故障的支付服务实例没有接入流量防控组件,则支付服务集群中的其他稳定的实例也会受到影响,从而导致支付服务集群出现“整体不可用”。这样整个交易服务就会出现“雪崩”现象。

6.2 认识Sentinel

6.3 将应用接入Sentinel

6.3.1 搭建Sentinel控制台

6.3.2 【实例】用Sentinel Core手动地将应用接入Sentinel

6.3.3 【实例】用Spring Cloud Alibaba Sentinel将应用接入Sentinel

6.4 用HTTP或者Netty实现通信渠道

6.4.1 认识NIO框架Netty

6.4.2 用SPI机制实现插件化通信渠道的原理

6.4.3 “用插件类NettyHttpCommandCenter实现通信渠道”的原理

6.4.4 “用SimpleHttpCommandCenter类实现通信渠道”的原理

6.4.5 【实例】用Netty实现通信渠道,实现“从应用端到Sentinel控制台的流量控制规则推送”

6.5 用过滤器和拦截器实现组件的适配

6.5.1 什么是过滤器和拦截器

6.5.2 “Sentinel通过过滤器适配Dubbo”的原理

6.5.3 “Sentinel通过拦截器适配Spring MVC”的原理

6.5.4 【实例】将Spring Cloud Gateway应用接入Sentinel,管理流量控制规则

6.6 用“流量控制”实现流量防护

6.6.1 什么是流量控制

6.6.2 槽位(Slot)的动态加载机制

6.6.3 “加载应用运行的监控指标”的原理

6.6.4 “用QPS/并发线程数实现流量控制”的原理

6.6.5 “用调用关系实现流量控制”的原理

6.6.6 【实例】通过控制台实时地修改QPS验证组件的流量防控

6.7 用“熔断降级”实现流量防护

6.7.1 什么是熔断降级

6.7.2 “实现熔断降级”的原理

6.7.3 【实例】用“模拟Dubbo服务故障”验证服务调用熔断降级的过程

6.8 用“系统自适应保护”实现流量防护

6.8.1 什么是“系统自适应保护”

6.8.2 “系统自适应保护”的原理

6.8.3 【实例】通过调整应用服务的入口流量和负载,验证系统自适应保护

6.9 用Nacos实现规则的动态配置和持久化

6.9.1 为什么需要“规则的动态配置”

6.9.2 为什么需要“规则的持久化”

6.9.3 “规则的动态配置”的原理

6.9.4 “规则的持久化”的原理

6.9.5 【实例】将Dubbo应用接入Sentinel,实现规则的动态配置和持久化