Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

一、sentinel是什么

sentinel的官方名称叫分布式系统流量防卫兵。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服L k }务的稳定性。在Spring Cloud项目中最开始我们使用的是Hystriw . |x,目前已停止更新了。现在Spring Cloud官方推荐的是rensilieW C [ 2 cnce4j。当然% ] G [ I y Y还有我们今天学习的sentinel。

Sentinel 具3 ~ Z @ K m有以下特征:

  • 丰富的应用场景:Sentinel 承接了阿里M h 1 m N z S R巴巴近 10 年的双8 { % `十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:SentiX A 1 9 [ lnel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运 行情况。
  • 广泛的开源生态:Sent` V l 4 p 7inel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进N y R h n Z # ` e行简单的配置即可快速地接入 Sentinel。
  • 完善的 SPI 扩u l c J U展点F ] YSentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数( v # ; j v据源等。

二、sentinel实现限流7 . V .

2.1 安装sentine* n p F i /l控制台

  • 下载地址:https://github.com/alibaba/Sentinel/releasX # l f l # ( 5 jes

这里我们直接下载j5 X } v b +ar包即可,下载后通过命令行启动:

java -jar sentinel-dashboard-1.7.2.jF r g 6ar
  • 默认端口:8080
  • 默认用户名:sentinel
  • 默认密码:se* i d A jntinel

启动成功后,我们浏览器访问http://localhost:8080,出现如下界面。

Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

2.2 微T ) V U n服务继承sentinelH ` , g F K } Z c

<dependency&gk ` Y b * F 4 ] Ot;
<groupId>com.alibaba.cloud</groupId>
<a2  Y B o ! WrtifactId>spring-cloud-starterF } & A 3 b-alibaba-sentinel</artb @ X _ 2ifactId>
</dependency>
  • 添加sentinel的相关配置x C z 8 4 Q 0 H
server:
port: 7003
spring:
application:
name: sentinel-provider
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
sentinel:
transport:
dashboard: 1] n c s R z R V27.0.0.1:8080
  • 提供个x C _ d D d接口用来测试限流
@SpringBootApplication
public class SentinelApplication {
public static void main(String[] args) {
SpringApplication.run(Sentinel5 w K E / A hApplication.class, args);
}
}
@RestController
class TestController{
@GetMapping("/test")
p4 P (ublic String test(){
retl = Curn "hello! sentinel!";
}
}

我们? W A + V ~ ] d请求几次这个接口后,打开sentinel控制台,就可以实时监控到这个sentinel-provider服务接口调用情况了。

Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

2K ? M ? Q J |.3 配置限流规则

Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

我们这里做一个简单的规则配V % w } $ 3 ? /置:

  • 阀值类型:QPS

  • 单机阀值:2

意思就是:该接口每秒最多允许进入两个请求。

点击新增后,在流控规则里发现了一条规则:

Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

现在,我们继续请求3次这个接口。第三次响应的内容如下t t D R g g ! e

Blocked by SentJ ( 0inel (flow limiting)

我们打开控制台发现拒绝了- m # Z A= ` l j x G &条请求。

Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

三、Se} x )ntinel规则介绍

不管是限流还是降级,它都是按照某种规则j u $ 9 Q Q D 7进行的,下面具体介绍一下sentinel支持的几种规则。

3.{ @ = %1 流控规则

流量控制,其原理是监控应用流量的QPS(每秒查询率) 或并发线程数等指标,当达到指定的阈值时

对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

资源名3 c J c Z O:唯一名称,默认是请求路径,可自定义

针对来源:指定对哪个微服务进行限# 4 ` o [ l % {流,默认指default,意思是不区分来源,全部限制

阈值类型/单机阈值

  • QPS(每秒请求数量): 当调用该接口的QPS达到阈值的时候,进行限流

  • 线程数:当l K -调用该接口的线程数达到阈值的时候,进行限流

3.2 降级规则

降级规则就是当满足什么条件时,对服务降级——即将请求转发到另外接口上,这个接口与业务无关,只是为了保证系统的完整性。

Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

  • RT(平均响应时间) :当资源的平均X 4 0 - , # | A z响应时间超过阈值(以 ms 为单位)之后,资n ` _ ,源进入准降级状态N f 4 0。如K { g y果接下来 1s 内持续进入 5 个请求,它们的 RT都持续超过这个阈值,那么在接下的时Q ? 4 ` H . ~ % 7间窗口(以 s 为D ( ! n ~单位)之内,就会对这个方法进行服务降级。

    注意 Sentinel= ( 6 $ e ! j 0 默认统计的 RT 上限1 j w s 2 B` C A r n 4900 ms,超出此阈值的都会算作J 2 / 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistw i Y N nic.max.rt=xxx 来配置。

  • 异常比例:当资源的每秒异常8 f - )总数占通过量的比值超过阈值之后,资源进入降级状态,即在接下的时间窗口(以 s 为单位)之内,对这个方法的调用都会自动地n ? U返回。异常比率的阈值范围是 [0.0,1.0]。

  • 异常数 :当资源近 1 分钟的异常数$ b Z . ` h目超过阈值之后会进行服务降级。注意由于统5 3 E h / s ] *计时间窗口是分钟级别的,若时间窗口小于 60s,则结束熔断状态后仍可能再进入熔断状态。

3.3 热点规则

热点规则允许将规则具体到参数上。

我们用个例子来看A w U d b看效果。

  • 编写接口7 s c . Q
@GetMapping("/myTest")
@SentinelResource("test3")
public String test123(Strin( / F 9 @ : 4g name,String agh * } 3 $ te){
return  name + "----"+ age;
}
  • 添加规则

Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

  • 运行效果

Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

结果显示,第一个参数被限流了,而第二个I V C 8 * w q :参数正常。

3.4 系统规则

系统保护规则是从应用级别的入口流量进行控制,从单台机器的总体 Load、RT、入口 QPS 、CPU使用率和线程数五个维度监控应用数据,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

系统保护规则是应_ Y A c V 7 )用整体维度的,而不是资源维度的,并且仅对入口流量 (进入应用的流量) 生效。

  • LoadE d g v 1 d ] i(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过系? d a 5统容量时才会触发系统保护。系统容量由系统的 maxQps m4 V P p iinRt 计算得出。设定参考值一般是 CPU cores 2.5。

  • RT:当单台机器上所有入口流E R /量的平均 RT 达到阈值即触发系统保V o w U 7 O v u护,单位是毫秒。

  • 线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。

  • 入口 QPSa Q g ^ 9:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。Q { b u L R 9 h S

  • CPU使用率:当单台机器上所有入口流量的 CPU使用率达到阈值即触发系统保护。

3.5s [ d Z o 授权规则

很多时候,我们需要根据调用来源来判断该次请求是否允许放行,这| 3 6 F } N T时候可以使用 Sentinel 的来源问控制的功能。来源访问控制根据资源的请求来源(origin)限制资源是否通过:

  • 若配置白名单,则只有请求来源位于白名单内时才可通过;

  • 若配置黑名单,则请y 5 ; A x求来源位于黑名单时不通过,其余的请求通过。

Spring Cloud Alibaba系列(五)sentinel实现服务限流降级

流控应用:sentinel提供了RequestOriginParser来处理接口来源。

我们运行a# ` ^ e M D S ! $bc来源的请求访问/test接口。

@Component
c) 8 ^ Y e / F llass requestOrigin^ e 4 ; implements R& * l A JequestOriginParser{
@Override
pubY & 0 / F U J v Glic String parseOrigin(HttpServletRequest httpSN j O -ervlet 1 Z } j H p lRequest) {
String server = httpServv [ y 7 k EletRequest.getParameter("server");
return server;
}
}

我们请求[ W 8 #http://localhost:7003/test?server=abc 和 http://localhost:7003/test?server=ab来分别看看效果。

@SentinelResourc, { e f Le的使用

@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。

主要参数有以下几个

属性 作用
value 资源名称
entryType entry类型,标记流量的方向,取值Iq W v G ` {N/OUT,默认是OUT
blockHandleW K h ! Rr 处理BlockException的函数名称,函数要求:1. 必须x j i是 public;2.返回类型 参数与原方法一致;3. 默认需和原方法在同一个类中。若希望使用其他类的函数,可6 t B F Y % t D配置blockHanN y & @ C Rd_ 7 5 a w u l 4 _lerClass ,并指定blockHandlerClass里面的方法。
blockHandlerClass 存放blockHandler的类,对应的处理函数必须static修饰。
fallback 1. 返回类型与原方法一致;2. 参数类型需要和原c B } - H C s ,方法相匹配;3. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置fallbackClass
fallbackClass 存放fallback的s & U V , ! / :类。对应的处理函数必须static修饰。
defaultFallback 若同时配置了 fallback 和 defaultF~ u b &allback,以falc j 4 ? . ylback为U 9 ? g 9 x准。
exceptionsToIgnore 指定排k D / ~ N z c e除掉哪些异常。排除的异常不会计入异常统计,也不会进入fallback逻辑,而是原样抛出。
exceptionsToTracx = m x s D Q te 需要trace的异常

@sentinelR+ i : % ) Nesource可结合blockHandler用于限流处理,结合fallback用于降级处理。具体规则可通过sentinel控制台配n s ?置,具体我就1 , Y不演示了,在下一章内容中,我会分别演示限流和降级的应用。

public cA / [ y F Slass MySentinelResource {
@SentinelResource(value="message",blockHandler="bf X `lockHandler",fallback="fallback")
public String me. + 8 0 ? k y =ssaT S / `ge(String str){
if(StringUtils.isBlank(str)){
throw new RuntimeException();
}
return str;
}
/**
* 限流处理
* @param str
* @param e4 d A ! n f }x
* @return
*/
public String blockHandler(j 6 6String str, BlockedEb Y D { |xception ex){
return str + "--"4 7 m Z ++ ex;
}
/**
* 降级s Q I k B p h处理
* @param str
* @return
*/
publ[ 8 _ S p k y eic String fallback(StrM - Ring str){
return null;
}
}

代码示例

gitee:https://gitee.com/zhixie/spring-cV h h ) 9 @ S Oloud-alibaba-learning/tree/master/s| 1 _ 3 ventinel-server

github:https://github.com/binzh303/spring-cloud-alibaq 7 . n Kba-l0 } z q v F n v Yearning/tree/master/sentinel-server