一、为什么使用Sentinel?
在我们日常生活中,经常会在淘宝、天猫、京东、拼多多等平台上参与商品的秒杀、抢购以及一些优惠活动,也会在节假日使用12306 手机APP抢火车票、高铁票,甚至有时候还要帮助同事、朋友为他们家小孩拉投票、刷票,这些场景都无一例外的会引起服务器流量的暴涨,导致网页无法显示、APP反应慢、功能无法正常运转,甚至会引起整个网站的崩溃。
Sentinel为了解决上述这些问题,由此应运而生。它通过为秒杀、抢购、抢票、拉票等功能提供API接口层面的流量限制,让突然暴涨而来的用户访问受到统一的管控,使用合理的流量放行规则使得用户都能正常得到服务。
二、什么是Sentinel?
Sentinel诞生于阿里巴巴,其主要目标是流量控制和服务熔断,2018年,Sentinel演变为一个开源项目现如今成为了Spring Cloud Alibaba的一个子项目。Sentinel是通过限制并发线程的数量(即信号隔离)来减少不稳定资源的影响,而不是使用线程池,省去了线程切换的性能开销。
当资源的响应时间变长时,线程将开始被占用。当线程数累积到一定数量时,新的传入请求将被拒绝。反之亦然,当资源恢复并变得稳定时,占用的线程也将被释放,新请求将被接受。
除了限制并发性外,Sentinel可以根据响应时间降级不稳定资源也是保证可靠性的有效方法。当资源的响应时间太大时,将在指定的时间窗口中拒绝所有对该资源的访问。-- 熔断机制
此外,Sentinel支持的熔断降级维度更多,可对多种指标进行流控、熔断,且提供了实时监控和控制面板,功能更为强大。
解决的问题:
(1)服务雪崩
(2)服务降级
(3)服务熔断
(4)服务限流
三、Sentinel如何使用?
1.Sentinel Server服务端
Sentinel 提供了现成的服务端供我们使用,点我下载地址,下载之后通过命令行启动
java -jar -Dserver.port=1111 sentinel-dashboard-1.6.0.jar
访问:http://127.0.0.1:1111
进入控制台,使用 sentinel/sentinel登录。
注意:只有1.6.0及以上版本才有这个登录页面。默认用户名和密码都是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 分钟; -
-Dserver.port=1111
:配置端口
主页面效果
2.Sentinel 客户端接入
导入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
配置Sentinel
修改yml配置,添加senticel服务控制台地址
spring:
cloud:
sentinel:
transport:
dashboard: localhost:1111
3.资源限流
Sentinel为我们提供了 @SentinelResource
注解标记需要限流的资源。 修改UserController,代码如下:
@Value("${server.port}")
private String port;
@Value("${redisss}")
private String redisss;
@GetMapping("/{id}")
//限流降级
@SentinelResource(value = "user",blockHandler = "currentLimiting",fallback = "fusing")
public User getUser(@PathVariable("id") Long id) {
// int i = 1 / 0; //方法异常,触发熔断
return new User(id,"天生我才","会须当饮三百杯" + port +";" +redisss );
}
//限流处理
public User currentLimiting(@PathVariable("id") Long id, BlockException e){
e.printStackTrace();
System.out.println("限流降级");
return new User(-1L,"山雨欲来风满楼","长风破浪会有时");
}
提示:这里通过@SentinelResource
的value属性为资源取名为 “user” ,后续我们可以根据该资源名来进行限流。
同时这里通过 blockHandler
属性我配置了一个限流降级方法,即当“user”资源触发限流了会调用blockHandler
指向的降级方法返回拖地数据,不至于抛出默认的限流异常信息给客户端(一串英文用户也看不懂) ,需要注意的是:降级方法要和被限流的方法参数一致,然后加上 BlockException异常对象。
当然,也可以通过 blockHandlerClass 属性把降级方法写在一个专门的类中,如:
@SentinelResource(value="user",blockHandler="exceptionHandler" ,blockHandlerClass=ExceptionUtil.Class)
降级类
public final class ExceptionUtil { public static User exceptionHandler(Long id ,lockException ex) { //... } }