我们在进行分布式系统的开发中,无论是在开发环境还是发布环境,配置一定不能是内存形式的,因为系统可能会在中途宕机或者重启,所以如果放在内存中,那么配置在服务停到就是就会消失,那么此时就需要重新再进行配置,一个两个服务还好,如果服务一多,那就是一件很费时费力的事情了。
所以我们还是需要把我们的配置信息持久化到配置中心,这也是目前主流的方式。
分布式系统中常见的配置中心有Nacos、ZooKeeper、Apollo、Consul等等,
本文中使用Nacos作为配置中心和服务中心。
配置持久化主要有以下原因:
在分布式的系统中,微服务是最基本的要求,所以我们就需要对微服务进行服务注册发现、配置和流控。
在微服务整合sentinel和Nacos是需要父pom中已经引入了spring-cloud-alibaba-dependencies
这个依赖,这个依赖中管理里当前版本中所有组件的版本信息。切记:在微服务中要特别注意各种依赖的版本。
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-datasource-nacosartifactId>
dependency>
spring:
application:
name: ${application_name}
main:
banner-mode: off
lazy-initialization: true
cloud:
nacos: # 配置nacos信息
discovery:
server-addr: ${nacos_server}
config:
server-addr: ${nacos_server}
file-extension: yaml
因为我们用nacos作为了配置中心,我们可以将sentinel的基本配置放入到nacos中就可以了,所以当前服务的yaml配置文件中只需要写一些基本的配置就可以了。
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 ##sentinel的控制面板地址
datasource: # sentinel用nacos作为数据源的配置
flux-control: # 流控管理(这个名称可以自定义)
nacos: # 告诉sentinel用nacos作为数据源
data-id: feign-test_flux-control_config.json # 配置中心里执行文件的dataId
server-addr: ${nacos_server} # nacos的地址
rule-type: flow # 指定文件配置的是那种规则
degrade-control: # 熔断管理(这个名称可以自定义)
nacos:
data-id: feign-test_degrade-control_config.json
server-addr: ${nacos_server}
rule-type: degrade
param-flow-control: # 热点参数管理(这个名称可以自定义)
nacos:
data-id: feign_test-hot_flux-config.json
server-addr: ${nacos_server}
rule-type: param-flow
我们使用nacos配置文件来对服务进行流控、熔断等操作,所以就需要有以下几个必须的参数:
com.alibaba.cloud.sentinel.datasource
包下的枚举类:RuleType
。public enum RuleType {
FLOW("flow", FlowRule.class),
DEGRADE("degrade", DegradeRule.class),
PARAM_FLOW("param-flow", ParamFlowRule.class),
SYSTEM("system", SystemRule.class),
AUTHORITY("authority", AuthorityRule.class),
GW_FLOW("gw-flow", "com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule"),
GW_API_GROUP("gw-api-group", "com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition");
//省略部分代码
}
我们这里使用的是配置文件的形式对sentinel的控制信息进行持久化,所以会存在一个问题:nacos中的配置文件对于sentinel来讲是单项数据读入,sentinel能监听到nacos中配置的变化,但是我们在sentinel中修改了配置,nacos是不会监听到并进行修改。
如果想进行双向绑定,就需要对sentinel的代码进行修改。
流控指的是流量控制
,也称作限流。它主要是用来限制每单位时间进入系统的请求数量,主要用来保证系统的可用性,防止大流量把系统压死。
[
{
"resource": "/test", // 资源名
"limitApp": "default", // // 针对来源,若为 default 则不区分调用来源
"grade": 1, // 限流阈值类型(1:QPS; 0:并发线程数)
"count": 1, // 阈值
"clusterMode": false, // 是否是集群模式
"controlBehavior": 0, // 流控效果 (0:快速失败; 1:Warm Up(预热模式); 2:排队等待)
"strategy": 0, // 流控模式(0:直接; 1:关联; 2:链路)
"warmUpPeriodSec": 10, // 预热时间(秒,预热模式需要此参数)
"maxQueueingTimeMs": 500, // 超时时间(排队等待模式需要此参数)
"refResource": "rrr" // 关联资源、入口资源(关联、链路模式)
}
]
在微服务中,熔断降级是一种保障服务稳定性的策略。
熔断降级可以简单理解为一个“保险丝”的作用。当某个服务发生严重故障(例如超时、异常等),为了防止整个系统的崩溃,会切断对这个服务的调用。这就像电流过大,保险丝会熔断以保护电路。
具体来说,熔断降级有两个目的:
防止应用程序不断地尝试执行可能会失败的操作给系统造成“雪崩”。
当某个服务提供者发生故障的时候,向调用方返回一个错误响应或者替代响应,而不是让调用方等待超时。
这样,即使个别服务出现问题,整个系统的运行也不会受到影响,这就是熔断降级的作用。
[
{
"resource": "/degrade",
"grade": 0, // 熔断策略,支持慢调用比例(0),异常比例(1),异常数(2)策略
"count": 1000, // 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用,单位ms);异常比例/异常数模式下为对应的阈值
"slowRatioThreshold": 0.1,// 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)
"minRequestAmount": 10, //熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断
"timeWindow": 10, // 熔断时长,单位为 s
"statIntervalMs": 1000 // 统计时长(单位为 ms),如 60*1000 代表分钟级
}
]
在微服务中,热点参数限流是一种特殊的限流方法。
热点参数限流主要是对参数值相同的请求进行分别统计,判断是否超过每秒事务处理量(QPS)的阈值。这种方法相较于传统的限流方式,更精细化和个性化,可以针对具体的应用和服务的瓶颈进行限流。
例如,在一个微服务系统中,“查询用户信息”这个服务可能存在一个热点参数“用户ID”,我们可以通过热点参数限流来控制单位时间内对同一个用户ID的查询请求数量,防止因为某个热点的参数导致整体服务的故障。
[
{
"resource": "/test1",
"grade": 1, // 限流模式(QPS 模式,不可更改)
"paramIdx": 0, // 参数索引
"count": 13, // 单机阈值
"durationInSec": 6, // 统计窗口时长
"clusterMode": false, // 是否集群 默认false
"controlBehavior": 0, // 流控效果(支持快速失败和匀速排队模式)
"limitApp": "default",
// 高级选项
"paramFlowItemList": [{
"classType": "int", // 参数类型
"count": 222, // 限流阈值
"object": "2" // 参数值
}]
}
]
系统规则是用于定义和配置分布式系统的流量控制和防护的一种策略。
可以根据不同的维度(如Load、CPU使用率、总体平均RT、入口QPS和并发线程数等)来设定系统保护规则,以保证系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
[
{
"avgRt": 1, // RT
"highestCpuUsage": -1, // CPU 使用率
"highestSystemLoad": -1, // LOAD
"maxThread": -1, // 线程数
"qps": -1, // 入口 QPS
"count": 55, // 阈值,在CPU使用率中是百分比
}
]
授权规则是用于控制服务请求者访问受保护资源的一种权限判断。它可以基于请求的来源或其他因素,对请求进行授权或者拒绝。
授权规则有多种实现方式,例如白名单和黑名单。白名单是允许来源在白名单内的调用者访问受保护资源,而黑名单则是禁止来源在黑名单内的调用者访问受保护资源。
在Sentinel中,可以通过自定义RequestOriginParser接口,从请求对象中获取请求者的来源,并按照白名单或黑名单的规则进行授权判断。
[
{
"resource": "sentinel_spring_web_context",
"limitApp": "/test",
"strategy": 0 // 授权类型(0代表白名单;1代表黑名单。)
}
]
在分布式系统中,一般使用Gateway网关来作为系统的入口,整合了网关后,请求会通过Gateway进行转发,就相当于Servlet中的forward,转发过程不会在浏览器中进行记录。
所以当我们为系统添加了Gateway之后,我们就可以不为每一个微服务添加流控效果了,只需要在Gateway中设置流控就可以了。
我们在Gateway中进行流控、熔断等操作,resource指的就是我们的服务名称。
Gateway的流控配置和普通的流控配置不一样。
[
{
"resource": "feign-test", // 资源名
"resourceMode": 0, // API类型, 0: ROUTE ID区分, 1: API
"count": 1, // 阈值,QPS类型就是限制时间间隔的请求数,线程数类型就是指并行的线程数
"grade": 1, // 阈值类型,0:线程数,1:QPS
"controlBehavior": 2, // 流控方式,0:快速失败,2:匀速排队
"intervalSec": 10, // 间隔,单位是秒
"burst": 0, // burst,只有在快速失败时才有效
"maxQueueingTimeoutMs": 1000 // 超时时间,单位是毫秒
}
]
参数名 | 参数描述 |
---|---|
resourceMode | API类型,0:ROUTE ID,1:API |
resource | 资源名 |
grade | 阈值类型,0:线程数,1:QPS |
count | 阈值,QPS类型就是限制时间间隔的请求数,线程数类型就是指并行的线程数 |
intervalSec | 间隔 ,单位是秒 |
controlBehavior | 流控方式,0:快速失败,2:匀速排队 |
burst | 额外流量,快速失败流控方式下,允许突出的流量数 |
maxQueueingTimeoutMs | 排队时间,单位是毫秒,匀速排队流控方式下,允许排队的时间 |
paramItem | 请求属性key,json对象,为配置的json key,value就是余下的配置项 |
parseStrategy | 参数属性,0 :ClientIP,1:RemoteHost,2:Header ,3:URL参数,4 Cookie |
fieldName | 参数名称,若参数属性选择 Header 模式或 URL 参数模式,则需要指定对应的 header 名称或 URL 参数名称 |
matchStrategy | 参数值匹配策略,0: 精确匹配,1:子串查询匹配,2:正则表达式匹配 |
pattern | 参数值匹配内容,按匹配策略来配置的值,只有匹配该模式的请求属性值会纳入统计和流控;若为空则统计该请求属性的所有值。 |
datasource
配置下的rule-type
参数值就得是gw_flow
, 不能是flow
,但也不是一定不能。spring:
cloud:
sentinel:
transport:
dashboard: http://localhost:8080
datasource:
flow-control:
nacos:
server-addr: ${nacos_server}
data-id: gateway_flux-control_config.json
# rule-type: flow
rule-type: gw_flow
1、如果配置的是
flow
,那么在sentinle中就不会显示处Gateway的流控配置,但是不影响功能。
2、如果配置的是gw_flow
,才会在sentinel中显示Gateway的流控配置,同时也不影响功能。
Gateway的熔断降级配置和之前的配置是一样的。
[
{
"resource": "feign-test", // 资源名
"count": 1000, // 当熔断策略是慢调用时,此值为最大RT,单位是毫秒。当熔断是策略是异常比例时,此值为异常比例。当熔断策略是异常数时,此值为异常数目
"timeWindow": 5, // 熔断时长,单位是秒
"grade": 0, // 0: 慢调用, 1: 异常比例,2:异常数
"minRequestAmount": 2, // 最小请求数
"slowRatioThreshold": 0.2, // 比例阈值
"statIntervalMs": 10000 // 统计时长,单位毫秒
}
]