背景
在微服务架构下,每个服务的性能都不同,为避免出现流量洪峰将服务冲垮,需要依赖限流工具来保护服务的稳定性。sentinel是阿里提供的限流工具,社区活跃,功能也很全面,包含实时监控、流控、熔断等功能。它也提供了spring-cloud-gateway的支持,可以很方便和spring-gateway进行整合。
目标
spring-gateway服务添加sentinel支持,并通过sentinel dashboard进行规则配置,规则数据存在nacos里,支持规则变更实时生效。
方案
服务结构
spring-gateway改动
引入工程依赖
在pom文件里添加sentinel的依赖:
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| <!--sentinel支持spring-->
<dependency>
``<groupId>com.alibaba.cloud</groupId>
``<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--自动集成spring gateway-->
<dependency>
``<groupId>com.alibaba.cloud</groupId>
``<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!--支持nacos的动态数据源-->
<dependency>
``<groupId>com.alibaba.csp</groupId>
``<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
|
加载限流规则
在application.properties文件里添加sentinel规则对应nacos配置信息:
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| project.name=spring-gateway
sentinel.nacos.``default``.namespace=SENTINEL_GROUP
spring.cloud.sentinel.datasource.gw_api_group.nacos.server-addr=${spring.cloud.nacos.config.server-addr}
spring.cloud.sentinel.datasource.gw_api_group.nacos.namespace=${spring.cloud.nacos.config.namespace}
spring.cloud.sentinel.datasource.gw_api_group.nacos.data-id=${project.name}-gw_api_group-rules
spring.cloud.sentinel.datasource.gw_api_group.nacos.group-id=${sentinel.nacos.``default``.namespace}
spring.cloud.sentinel.datasource.gw_api_group.nacos.data-type=json
spring.cloud.sentinel.datasource.gw_api_group.nacos.rule-type=gw_api_group
spring.cloud.sentinel.datasource.gw_flow.nacos.server-addr=${spring.cloud.nacos.config.server-addr}
spring.cloud.sentinel.datasource.gw_flow.nacos.namespace=${spring.cloud.nacos.config.namespace}
spring.cloud.sentinel.datasource.gw_flow.nacos.data-id=${project.name}-gw_flow-rules
spring.cloud.sentinel.datasource.gw_flow.nacos.group-id=${sentinel.nacos.``default``.namespace}
spring.cloud.sentinel.datasource.gw_flow.nacos.data-type=json
spring.cloud.sentinel.datasource.gw_flow.nacos.rule-type=gw_flow
spring.cloud.sentinel.datasource.degrade.nacos.server-addr=${spring.cloud.nacos.config.server-addr}
spring.cloud.sentinel.datasource.degrade.nacos.namespace=${spring.cloud.nacos.config.namespace}
spring.cloud.sentinel.datasource.degrade.nacos.data-id=${project.name}-degrade-rules
spring.cloud.sentinel.datasource.degrade.nacos.group-id=${sentinel.nacos.``default``.namespace}
spring.cloud.sentinel.datasource.degrade.nacos.data-type=json
spring.cloud.sentinel.datasource.degrade.nacos.rule-type=degrade
spring.cloud.sentinel.datasource.system.nacos.server-addr=${spring.cloud.nacos.config.server-addr}
spring.cloud.sentinel.datasource.system.nacos.namespace=${spring.cloud.nacos.config.namespace}
spring.cloud.sentinel.datasource.system.nacos.data-id=${project.name}-system-rules
spring.cloud.sentinel.datasource.system.nacos.group-id=${sentinel.nacos.``default``.namespace}
spring.cloud.sentinel.datasource.system.nacos.data-type=json
spring.cloud.sentinel.datasource.system.nacos.rule-type=system
spring.cloud.sentinel.datasource.authority.nacos.server-addr=${spring.cloud.nacos.config.server-addr}
spring.cloud.sentinel.datasource.authority.nacos.namespace=${spring.cloud.nacos.config.namespace}
spring.cloud.sentinel.datasource.authority.nacos.data-id=${project.name}-authority-rules
spring.cloud.sentinel.datasource.authority.nacos.group-id=${sentinel.nacos.``default``.namespace}
spring.cloud.sentinel.datasource.authority.nacos.data-type=json
spring.cloud.sentinel.datasource.authority.nacos.rule-type=authority
spring.cloud.sentinel.datasource.param_flow.nacos.server-addr=${spring.cloud.nacos.config.server-addr}
spring.cloud.sentinel.datasource.param_flow.nacos.namespace=${spring.cloud.nacos.config.namespace}
spring.cloud.sentinel.datasource.param_flow.nacos.data-id=${project.name}-param_flow-rules
spring.cloud.sentinel.datasource.param_flow.nacos.group-id=${sentinel.nacos.``default``.namespace}
spring.cloud.sentinel.datasource.param_flow.nacos.data-type=json
spring.cloud.sentinel.datasource.param_flow.nacos.rule-type=param_flow
|
限流处理
请求击中限流规则后,我们要对限流异常进行处理。可以通过自定义BlockRequestHandler来定制处理逻辑,也可以使用sentinel spring gateway的默认处理器,支持需要在配置文件里加上一下信息:
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # mode=response代表正常返回响应,mode=redirect代表重定向某个页面
spring.cloud.sentinel.scg.fallback.mode=response
spring.cloud.sentinel.scg.fallback.response-body={``"success"``: ``false``, ``"message"``:``"too many requests(flow limiting)"``, ``"code"``: ``429``}
spring.cloud.sentinel.scg.fallback.response-status=429
|
sentinel dashboard部署
sentinel dashboard是sentinel的管理后台代码,做了定制支持nacos,代码在仓库:GitHub - xsg22/Sentinel at sentinel-nacos-1.8
通过maven打出jar包后,支持传到服务器上进行部署。也可以使用已有的jar:https://download.csdn.net/download/xsgnzb/88522419
部署完整命令如下:
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| java -jar sentinel-dashboard.jar --auth.enabled=``true
--auth.username=admin --auth.password=123456 --server.port=9090 --spring.cloud.nacos.config.namespace=xxx --spring.cloud.nacos.config.server-addr=xxx
|
部署的时候要注意几个参数:
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # 访问端口
server.port=``9090
# 登录账号
auth.enabled=``true
auth.username=admin
auth.password=``123456
# nacos连接地址
spring.cloud.nacos.config.server-addr=xxx
spring.cloud.nacos.config.namespace=xxx
|
数据源
sentinel包含7种规则类型,这些规则数据存放在nacos里。配置格式是,dataId={[project.name](http://project.name/ "project.name")}-{ruleType}-rules,group=SENTINEL_GROUP。例如,限流规则对应的dataId=spring-gateway-gw_flow-rules。
这是sentinel定义的RuleType:
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| public
enum
RuleType {
``/**
``* 限流规则,非网关模式
``*/
``FLOW(``"flow"``, FlowRule.``class``),
``/**
``* 降级规则
``*/
``DEGRADE(``"degrade"``, DegradeRule.``class``),
``/**
``* 根据请求参数进行限流的规则
``*/
``PARAM_FLOW(``"param-flow"``, ParamFlowRule.``class``),
``/**
``* 系统规则,根据cpu使用率、load指标进行限流
``*/
``SYSTEM(``"system"``, SystemRule.``class``),
``/**
``* 授权规则,app的白名单/黑名单
``*/
``AUTHORITY(``"authority"``, AuthorityRule.``class``),
``/**
``* 限流规则,网关模式
``*/
``GW_FLOW(``"gw-flow"``,
``"com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule"``),
``/**
``* api定义信息
``*/
``GW_API_GROUP(``"gw-api-group"``,
``"com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition"``);
}
|
注意,使用网关模式对接时,限流规则不能放到flow类型下,要使用gw_flow类型。