目录
简介
Sentinel是面向分布式服务框架的轻量级流量控制框架,主要以流量为切入点,从流量控制,熔断降级,系统负载保护等多个维度来维护系统的稳定性。 在SpringCloud体系中,Sentinel主要是为了替换原Hystrix的功能,与Hystrix相比,Sentinel的隔离级别更加精细,提供的Dashboard可以在线更改限流熔断规则,而且使用也越加方便。要了解更多详细信息请移步至Sentinel官网。
基础准备
安装配置
使用docker安装sentinel 1.8.0
docker pull bladex/sentinel-dashboard:1.8.0
更改配置文件
复制到docker-compose.yaml 与 mysql nacos 同级别
sentinel:
image: bladex/sentinel-dashboard:1.8.0
container_name: sentinel
ports:
- "8858:8858"
restart: always
//启动sentinel
docker-compose up -d sentinel
开启端口
云服务器:开启8858 配置规则
或
虚拟机:
// 开启端口
firewall-cmd --zone=public --add-port=8858/tcp --permanent
// 重启防火墙
firewall-cmd --reload
测试访问
账号密码:sentinel
引入Sentinel
在需要配置限流熔断服务的POM文件中引入Sentinel组件
这里我们对账户服务进行限流
<!--添加sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
自定义资源@SentinelResource
我们只需要在相关方法上加上@SentinelResource注解,让其可以成为sentinel识别的资源即可。
@SentinelResource(value = "getAccountByUserId")
@GetMapping("/getAccountByUserId/{id}")
public Result getAccountByUserId(@PathVariable("id")Integer id){
LambdaQueryWrapper<Account> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Account::getId,id);
Account account = accountService.getOne(wrapper);
if(account==null)
{
throw new BusinessException(ResultCode.USER_ACCOUNT_NOT_EXIST.getCode(),
ResultCode.USER_ACCOUNT_NOT_EXIST.getMessage());
}
return Result.ok().data("account",account).data("port",port);
}
在Account配置文件中添加sentinel的服务端地址
sentinel:
transport:
port: 8719
dashboard: localhost:8858 # sentinel的控制台
clientIp: localhost
eager: true # 取消延迟加载
enabled: true
使用服务器需要操作下面这一步 虚拟机的可以直接跳过这一段进行测试
下载 sentinel-dashboard-1.8.0.jar
在放置的文件夹上cmd 运行下面这段话
java -jar -Dserver.port=8858 sentinel-dashboard-1.8.0.jar
测试
Sentinel控制台查看
如果没有多刷新访问几次 会有延迟
添加限流
反复刷新访问出现 500说明成功
对页面进行处理
@SentinelResource(value = "getAccountByUserId",blockHandler = "flowHandler")
@GetMapping("/getAccountByUserId/{id}")
public Result getAccountByUserId(@PathVariable("id")Integer id){
LambdaQueryWrapper<Account> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Account::getId,id);
Account account = accountService.getOne(wrapper);
if(account==null)
{
throw new BusinessException(ResultCode.USER_ACCOUNT_NOT_EXIST.getCode(),
ResultCode.USER_ACCOUNT_NOT_EXIST.getMessage());
}
return Result.ok().data("account",account).data("port",port);
}
//自定义异常策略
//返回值和参数要跟目标函数一样,参数可以追加BLockException
public Result flowHandler(@PathVariable("id")Integer id,BlockException e){
//虽然在这里这些参数看似毫无意义,但是在实战中,这些参数我们可以存入到消息队列
//配合消息队列或者数据库对失败的操作进行一个手动处理
e.printStackTrace();
return Result.error().message("访问过于频繁,请稍后重试");
}
重启服务需要重新添加流控
sentniel持久化限流规则
每次重启都需要重新添加限流 很麻烦,所以需要进行持久化来解决这个问题
account-service pom.xml引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.8.0</version>
</dependency>
yaml
sentinel:
eager: true # 取消延迟加载
transport:
port: 8719
dashboard: localhost:8858 # sentinel的控制台
clientIp: localhost
datasource:
ds:
nacos:
server-addr: 106.55.10.118:8848 #nacos的服务注册中心
group-id: DEFAULT_GROUP #nacos配置中心的组id
data-id: account-sentinel.json #这是唯一的数据id
rule-type: flow #规则为限流
nacos添加配置
[
{
"resource": "getAccountByUserId",
"limitApp": "default",
"grade": 1,
"count": 3,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
nacos添加后重启服务 可查看流控的存在
添加降级
假设我们访问了5次但是又两次是超时的,40%=0.4
这个时候会触发熔断机制,熔断时间表示我们在这个熔断的时间内,不管怎么访问都是返回的熔断处理
熔断一般是出现了异常,或者访问资源超时,都会触发熔断机制
这个不好演示 直接抛出异常
@SentinelResource(value = "getAccountByUserId",blockHandler = "flowHandler",
fallback= "fallbackHandler")
@GetMapping("/getAccountByUserId/{id}")
public Result getAccountByUserId(@PathVariable("id")Integer id){
LambdaQueryWrapper<Account> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Account::getId,id);
Account account = accountService.getOne(wrapper);
if(account==null)
{
throw new BusinessException(ResultCode.USER_ACCOUNT_NOT_EXIST.getCode(),
ResultCode.USER_ACCOUNT_NOT_EXIST.getMessage());
}
//return Result.ok().data("account",account).data("port",port);
throw new RuntimeException("error");
}
//自定义异常策略
//返回值和参数要跟目标函数一样,参数可以追加BLockException
public Result flowHandler(@PathVariable("id")Integer id,BlockException e){
//虽然在这里这些参数看似毫无意义,但是在实战中,这些参数我们可以存入到消息队列
//配合消息队列或者数据库对失败的操作进行一个手动处理
e.printStackTrace();
return Result.error().message("访问过于频繁,请稍后重试");
}
public Result fallbackHandler(@PathVariable("id") Integer id){
return Result.error().message("触发了熔断机制");
}
测试
配置隔离
引入配置中心组件spring-cloud-starter-alibaba-nacos-config
<!--nacos的配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--2020/2021的SpringCloud才需要引入这个,不然无法读取Bootstrap.yaml文件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
nacos新建命名空间
在account下新建配置
将application.yaml内容 复制过来
删除 application.yaml
创建 bootstrap.yaml
spring:
application:
name: account_service
cloud:
nacos:
config:
server-addr: 192.55.10.118:8848
file-extension: yaml
group: DEFAULT_GROUP
namespace: 51590662-b609-44b5-b834-e7042a73a9c9
namespace 是tenant_id字段
重启测试成功即可!