Spring Cloud Alibaba 微服务一 - nacos
Spring Cloud Alibaba 微服务二 - 服务注册与发现
Spring Cloud Alibaba 微服务三 - gateway网关
Spring Cloud Alibaba 微服务四 - sentinel服务限流与降级
Spring Cloud Alibaba 微服务五 - seata分布式事务
什么是Sentinel
Sentinel(分布式系统的流量防卫兵)是阿里开源的一套用于服务容错的综合性解决方案。它们流量为切入点,从流量控制,熔断降级,系统负载保护等多个维度来保护服务的稳定性。
Sentinel具有以下特征:
- 丰富的应用场景:Sentinel承接了阿里巴巴近10年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围),消息削峰填谷。集群流量控制,实时熔断下游不可用应用等。
- 完备的实时监控:Sentinel提供了实时的监控功能。通过控制可以看到接入应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况。
- 广泛的开源生态:Sentinel提供开箱即用的与其他开源框架/库的整合模块,例如与SpringCLoud,Dubbo,gRPC的整合。只需要进入相应的依赖并进行简单的配置即可快速地接入Sentinel。
完善的SPI扩展点:Sentinel提供简单易用,完善的SPI扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理,适配动态数据源等。
Sentinel分为两个部分:
- 核心(Java客户端)不依赖任何框架/库,能够运行于所有Java运行时环境,同时对Dubbo/Spring Cloud等框架也有比较好的支持。
- 控制台(Dashboard)基于Spring Boot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器。
部署sentinel
下载链接:https://github.com/alibaba/Sentinel/releases.
通过启动命令
java -jar sentinel-dashboard-1.6.0.jar
#由于sentinel-dashboard是一个标准的spring boot应用,所以如果要自定义端口号等内容的话,可以通过在启动命令中增加参数来调整,比如:-Dserver.port=8888。
正常启动成功的话,访问对应的地址会看到以下界面,默认的账号/密码为:sentinel/sentinel
启动时可通过一下参数修改账号密码:
-Dsentinel.dashboard.auth.username=sentinel: 用于指定控制台的登录用户名为 sentinel;
-Dsentinel.dashboard.auth.password=123456: 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel
-Dserver.servlet.session.timeout=7200: 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;
微服务集成sentinel
1.在pom加入依赖
<!--Sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.编写一个测试的controller
3.配置sentinel
spring:
cloud:
sentinel:
transport:
port: 9999
dashboard: 192.168.110.130:8080
4.启动后访问controller,在sentinel 客户端可以看见
实现限流
快速访问接口:
自己手写返回异常:
@GetMapping
@SentinelResource(value = "getblog", blockHandler = "get")
public Result get(String uid, int current, int size) {
return new Result(blogService.get(uid, current, size));
}
//参数和原来的相同多了一个BlockException
public Result get(String uid, int current, int size, BlockException exception) {
return Result.build(900, "访问速度太块啦");
}
重新配置流控,快速访问
sentinel持久化
前面我们介绍了sentinel控制台以及客户端的启动,并且实现了在控制台添加流控以及熔断规则,并且将规则发送给客户端。但是,将客户端重启或者sentinel客户端重启,我们会发现,我们之前设置的规则将会丢失,这是因为客户端将规则保存在内存中,并没有将其持久化,因而,这样并不适用于生产环境。
我们通过修改sentinel源码将Sentinel控制台熔断规则推送到Nacos数据源。
源码地址: https://github.com/alibaba/Sentinel.
1.修改pom文件,将sentinel-datasource-nacos的 test 这一行注释掉
<!-- for Nacos rule publisher sample -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<!-- <scope>test</scope>-->
</dependency>
2.找到 sentinel-dashboard/src/test/java/com/alibaba/csp/sentinel/dashboard/rule/nacos目录,将整个目录拷贝到 sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos
3.修改NacosConfig类,修改NacosIP地址
4.修改com.alibaba.csp.sentinel.dashboard.controller。FlowControllerV1
注入
@Autowired
@Qualifier("flowRuleNacosProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleNacosPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
修改rules接口,读取nacos中的数据
@GetMapping("/rules")
@AuthAction(PrivilegeType.READ_RULE)
public Result<List<FlowRuleEntity>> apiQueryMachineRules(@RequestParam String app,
@RequestParam String ip,
@RequestParam Integer port) {
if (StringUtil.isEmpty(app)) {
return Result.ofFail(-1, "app can't be null or empty");
}
if (StringUtil.isEmpty(ip)) {
return Result.ofFail(-1, "ip can't be null or empty");
}
if (port == null) {
return Result.ofFail(-1, "port can't be null");
}
try {
List<FlowRuleEntity> rules = ruleProvider.getRules(app);
if (rules != null && !rules.isEmpty()) {
for (FlowRuleEntity entity : rules) {
entity.setApp(app);
if (entity.getClusterConfig() != null && entity.getClusterConfig().getFlowId() != null) {
entity.setId(entity.getClusterConfig().getFlowId());
}
}
}
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);
} catch (Throwable throwable) {
logger.error("Error when querying flow rules", throwable);
return Result.ofThrowable(-1, throwable);
}
}
修改该类最后的publishRules
private CompletableFuture<Void> publishRules(String app, String ip, Integer port) {
List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
try {
rulePublisher.publish(app, rules);
logger.info("添加限流规则成功.....");
} catch (Exception e) {
e.printStackTrace();
logger.info("添加限流规则失败.....");
}
return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);
}
重新打包mvn clean package -pl sentinel-dashboard -am 运行
添加流控规则后在nacos可以看见
项目github地址 https://github.com/XSWgrzh/xsw.
更详细: https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5.