享学课堂特邀作者:老顾
转载请声明出处!!!
前言
之前老顾介绍了gateway集合sentinel1.8的整体概念介绍,今天老顾就来介绍一下,gateway如何与sentinel相结合,sentinel1.8降级规则的变化,以及dashboard源码的bug。
POM依赖
我们先创建一个gateway项目,要与Sentinel结合需要依赖一下jar包。
说明一下老顾把以前文章中的案例依赖的jar包进行了升级,针对SpringCloud Alibaba的版本需要升级到2.2.3.RELEASE版本;spring boot也升级到了2.3.3.RELEASE;spring cloud升级到Hoxton.SR8
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
不要搞错了哦,网上有些资料有坑
配置
网关项目中增加一个配置类,我们需要添加一个SentinelGatewayFilter和SentinelGatewayBlockExceptionHandler实例

之前老顾的文章已经介绍过了
1、下载地址:https://github.com/alibaba/Sentinel/releases根据自己需要下载对应版本,这里以sentinel-dashboard-1.8.0.jar为例
2、上传控制台jar包至linux服务器,启动sentinel控制台命(端口被占用请修改端口):
nohup java -Dserver.port=8081 -Dcsp.sentinel.dashboard.server=localhost:8081 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.0.jar &
3、访问后台:http://localhost:8081,用户名、密码默认都为:sentinel,也可在启动命令中自行配置

为网关增加JVM启动参数
-Dcsp.sentinel.dashboard.server=localhost:8081
-Dproject.name=qy-tribe-gateway
-Dcsp.sentinel.api.port=8719
-Dcsp.sentinel.app.type=1
参数说明: -Dcsp.sentinel.dashboard.server:指定控制台地址和端口。
-Dproject.name:在sentinel控制台中展示的项目名称。
-Dcsp.sentinel.api.port:指定客户端监控 API 的端口(默认是 8719),如控制台修改规则,则会向该端口推送规则信息。
-Dcsp.sentinel.app.type:从 1.6.3 版本开始,控制台支持网关流控规则管理。该启动参数会将您的服务标记为 API Gateway,在接入控制台时您的服务会自动注册为网关类型,然后您即可在控制台配置网关规则和 API 分组。
配置方案
上面的jvm启动参数,另一个方案就是在yml配置文件中配置
##Sentinel 控制台地址
spring.cloud.sentinel.transport.dashboard = localhost:8081
##客户端监控API的端口
spring.cloud.sentinel.transport.port = 8719
##取消Sentinel控制台懒加载,即项目启动即连接
sentinelspring.cloud.sentinel.eager = true
上面的dashboard地址的配置,以及transport.port配置和用启动参数的方案是一样的效果。
注意:网上有些资料说spring.cloud.sentinel.app.type = 1 可以标示为网关项目,但亲测试无效,所以必须在启动网关项目的时候,一定要加上-Dcsp.sentinel.app.type=1

我们发现网关项目的Sentinel菜单和普通微服务项目菜单是不一样的。小伙伴们要记住哦。
API 分组和route维度
Sentinel 1.6.0引入了Sentinel API Gateway Adapter Common模块,此模块中包含网关限流的规则和自定义 API 的实体和管理逻辑:
1、GatewayFlowRule:网关限流规则,这个根据网关的自身的路由场景设计的,可以针对不同 route 或自定义的 API 分组进行限流,支持针对请求中的参数、Header、来源 IP 等进行定制化的限流。
2、ApiDefinition:用户自定义的 API 定义分组,可以看做是一些 URL 匹配的组合。比如我们可以定义一个 API 叫 myapi,请求 path 模式为 /foo/* 和 /baz/* 的都归到 myapi 这个 API 分组下面。限流的时候可以针对这个自定义的 API 分组维度进行限流。
网关限流规则 GatewayFlowRule

字段解释如下:
1、resourceMode:API类型
规则是针对 API Gateway 的route(RESOURCEMODEROUTEID)还是用户在 Sentinel 中自定义的API 分组(RESOURCEMODECUSTOMAPINAME),默认是route。
2、resource:API名称
网关中的 route 名称或者用户自定义的API 分组名称。
3、请求属性:可选,paramItem参数限流配置。
若不提供,则代表不针对参数进行限流,该网关规则将会被转换成普通流控规则;否则会转换成热点规则。
其中的字段:parseStrategy:从请求中提取参数的策略,目前支持五种模式提取来源 IP 、Host 、 Header 、 URL 参数、Cookie pattern 和 matchStrategy:为参数匹配特性预留,匹配模式,匹配串 fieldName:若提取策略选择 Header 模式或 URL 参数模式,则需要指定对应的 header 名称或 URL 参数名称。

4、grade:阈值类型
限流阈值类型,是按照 QPS 还是线程数
5、count:限流阈值
6、intervalSec:间隔时间
统计时间窗口,单位是秒,默认是1 秒
7、controlBehavior:流控方式
目前支持快速失败和匀速排队两种模式,默认是快速失败。
8、burst
应对突发请求时额外允许的请求数目
9、maxQueueingTimeoutMs
匀速排队模式下的最长排队时间,单位是毫秒,仅在匀速排队模式下生效。
网关流控实现原理

上图的整体流程如下:
1、外部请求进入API Gateway时会经过Sentinel实现的filter,其中会依次进行 路由/API 分组匹配、请求属性解析和参数组装。
2、Sentinel 会根据配置的网关流控规则来解析请求属性,并依照参数索引顺序组装参数数组,最终传入SphU.entry(res, args) 中。
3、Sentinel API Gateway Adapter Common模块向 Slot Chain 中添加了一个 GatewayFlowSlot,专门用来做网关规则的检查。
4、GatewayFlowSlot会从GatewayRuleManager中提取生成的热点参数规则,根据传入的参数依次进行规则检查。若某条规则不针对请求属性,则会在参数最后一个位置置入预设的常量,达到普通流控的效果。注意:
当通过 GatewayRuleManager 加载网关流控规则GatewayFlowRule时,无论是否针对请求属性进行限流,Sentinel底层都会将网关流控规则转化为热点参数规则ParamFlowRule,存储在GatewayRuleManager 中,与正常的热点参数规则相隔离。转换时Sentinel会根据请求属性配置,为网关流控规则设置参数索引idx,并同步到生成的热点参数规则中
熔断降级

Sentinel在1.8.0版本对熔断降级做了大的调整,可以定义任意时长的熔断时间,引入了半开启恢复支持。下面梳理下相关特性。
一、熔断状态
熔断有三种状态,分别为OPEN、HALF_OPEN、CLOSED

二、熔断策略
熔断降级支持慢调用比例、异常比例、异常数三种熔断策略。
先明确下面两个概念:慢调用:指耗时大于阈值RT的请求称为慢调用,阈值RT由用户设置
最小请求数:允许通过的最小请求数量,在最小请求数量内不发生熔断,由用户设置
1.慢调用比例

执行逻辑
熔断(OPEN):请求数大于最小请求数并且慢调用的比率大于比例阈值则发生熔断,熔断时长为用户自定义设置。
探测(HALFOPEN):当熔断过了定义的熔断时长,状态由熔断(OPEN)变为探测(HALFOPEN)。
- 如果接下来的一个请求小于最大RT,说明慢调用已经恢复,结束熔断,状态由探测(HALF_OPEN)变更为关闭(CLOSED)
- 如果接下来的一个请求大于最大RT,说明慢调用未恢复,继续熔断,熔断时长保持一致
注意Sentinel默认统计的RT上限是4900ms,超出此阈值的都会算作4900ms,若需要变更此上限可以通过启动配置项-Dcsp.sentinel.statistic.max.rt=xxx来配置
2.异常比例
通过计算异常比例与设置阈值对比的一种策略。
当资源的每秒请求数大于等于最小请求数,并且异常总数占通过量的比例超过比例阈值时,资源进入降级状态。

执行逻辑
熔断(OPEN):当请求数大于最小请求并且异常比例大于设置的阈值时触发熔断,熔断时长由用户设置。
探测(HALFOPEN):当超过熔断时长时,由熔断(OPEN)转为探测(HALFOPEN)
- 如果接下来的一个请求未发生错误,说明应用恢复,结束熔断,状态由探测(HALF_OPEN)变更为关闭(CLOSED)
- 如果接下来的一个请求继续发生错误,说明应用未恢复,继续熔断,熔断时长保持一致
3.异常数
通过计算发生异常的请求数与设置阈值对比的一种策略
当资源近1分钟的异常数目超过阈值(异常数)之后会进行服务降级。注意由于统计时间窗口是分钟级别的,若熔断时长小于60s,则结束熔断状态后仍可能再次进入熔断状态。


执行逻辑
熔断(OPEN):当请求数大于最小请求并且异常数量大于设置的阈值时触发熔断,熔断时长由用户设置。
探测(HALFOPEN):当超过熔断时长时,由熔断(OPEN)转为探测(HALFOPEN)
- 如果接下来的一个请求未发生错误,说明应用恢复,结束熔断,状态由探测(HALF_OPEN)变更为关闭(CLOSED)
- 如果接下来的一个请求继续发生错误,说明应用未恢复,继续熔断,熔断时长保持一致
规则参数说明
熔断降级DegradeRule中的属性进行说明

Dashboard源码Bug
上面的规格参数中有个statIntervalMs这个属性默认1000ms,统计时长无法在dashboard中进行修改。
注意:1.8版本的Sentinel dashboard降级页面有个bug,就是统计时长属性维护 丢失,有望再下一个版本中修复;也可以自行修改dashboard源码
修改/sentinel-dashboard/src/main/webapp/resources/app/views/dialog/degrade-rule-dialog.html
增加一段html代码,统计时长代码
<div class="form-group">
<label class="col-sm-2 control-label">统计时长</label>
<div class="col-sm-4">
<div class="input-group">
<input type='number' min="1" class="form-control highlight-border" ng-model='currentRule.statIntervalMs'
placeholder="统计时长(ms)" />
<span class="input-group-addon">ms</span>
</div>
</div>
</div>
异常处理
当触发限流后页面显示的是Blocked by Sentinel: FlowException。
这个原理是DefaultBlockRequestHandler;实现了BlockRequesthandler接口

为了展示更加友好的限流提示, Sentinel支持自定义异常处理。
可以在GatewayCallbackManager注册回调进行定制:
setBlockHandler :注册函数用于实现自定义的逻辑处理被限流的请求,对应接口为 BlockRequestHandler 。默认实现为 DefaultBlockRequestHandler ,当被限流时会返回类似 于下面的错误信息:Blocked by Sentinel: FlowException 。
方案一:yml配置
spring.cloud.sentinel.scg.fallback.mode = response
spring.cloud.sentinel.scg.fallback.response-body = '{"code":403,"mes":"限流了"}'
上面的配置就可以达到自定义异常的效果。
方案二:注入Bean

Sentinel1.8对降级的重新进行的改造,变化相对比较大,小伙伴们需要进行详细学习哦!!!下面老顾会介绍Sentinel的规则持久化,对源码进行相应的改造,谢谢!

网友评论