Sentinel 服务限流
雪崩效应
高并发系统中,由一个小问题而引发的系统崩溃。
解决方案
- 设置线程超时,当某个请求在特定的时间内无法调通,则直接释放该线程。
- 设置限流,某个微服务到达访问上限之后,其他请求就暂时无法访问该服务。
- 熔断器,这是目前微服务中比较主流的解决方案,如 Hystrix,相当于家里的保险丝,如果电流过大,为了保护家电设备,自动烧断保险丝,断电,阻断电流。
1. Sentinel 基本接入步骤
1.1 pom.xml 引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
1.2 application.yml 配置
management:
endpoints:
web:
exposure:
include: '*'
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
1.3 启动 Sentinel 控制台
- 下载地址:https://github.com/alibaba/Sentinel/releases
- 启动命令(控制台默认端口 8080):
java -jar sentinel-dashboard-1.7.2.jar
- 浏览器访问:http://localhost:8080
启动服务后访问一次接口,再刷新控制台页面,就能看到监控数据。
2. 流控规则
直接限流
在 Sentinel 控制台中选择簇点链路,直接对指定资源(如 /index)设置 QPS 阈值。
关联限流
@RestController
public class SentinelController {
@Value("${server.port}")
private String port;
@GetMapping("/index")
public String index(){
return this.port;
}
@GetMapping("/list")
public String list(){
return "list";
}
}
模拟访问压力:
public class Test {
public static void main(String[] args) throws Exception {
RestTemplate restTemplate = new RestTemplate();
for (int i = 0; i < 1000; i++) {
restTemplate.getForObject("http://localhost:8280/list", String.class);
Thread.sleep(500);
}
}
}
链路限流(重点)
链路限流是一种更细粒度的限流方式,对某个资源(Service)在不同调用路径下分别进行限流控制。
⚠️ 注意:Sentinel 1.6.3+ 默认会将所有 URL 的 context 统一为
sentinel_web_context
,链路限流失效。
正确开启链路限流的步骤
1)pom.xml 添加依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-web-servlet</artifactId>
<version>1.7.1</version>
</dependency>
2)application.yml 禁用默认 Web Filter 收敛
spring:
cloud:
sentinel:
filter:
enabled: false
3)编写配置类,手动注册 CommonFilter
@Configuration
public class FilterConfiguration {
@Bean
public FilterRegistrationBean registrationBean(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new CommonFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY,"false");
registrationBean.setName("sentinelFilter");
return registrationBean;
}
}
4)Service 层定义资源
@Service
public class HelloService {
@SentinelResource("test")
public void test() {
System.out.println("test");
}
}
5)Controller 多路径调用资源
@RestController
public class TestController {
@Autowired
private HelloService helloService;
@GetMapping("/test1")
public String test1() {
this.helloService.test();
return "test1";
}
@GetMapping("/test2")
public String test2() {
this.helloService.test();
return "test2";
}
}
然后在 Sentinel 控制台中添加:
- 资源名称:
test
- 规则类型:链路
- 来源
/test1 → test
设置限流规则 - 来源
/test2 → test
不设置
这样就实现了“链路级别”的资源访问控制!
3. 流控效果
快速失败
超过阈值立即抛出异常,返回错误提示。
Warm Up(预热)
在应用刚启动时,预热期间单机 QPS 阈值较低,逐渐升至设定值。
- 初始:阈值为设置值的 1/3
- 过渡:按比例提升
- 最终:恢复到设定值
排队等待(匀速排队)
请求未被立即处理,而是进入等待队列,直到到达时间窗口内的空闲处理时间。
public class Test {
public static void main(String[] args) throws Exception {
RestTemplate restTemplate = new RestTemplate();
for (int i = 0; i < 1000; i++) {
restTemplate.getForObject("http://localhost:8280/index", String.class);
Thread.sleep(500);
}
}
}
总结
机制 | 描述 |
---|---|
直接限流 | 对资源本身进行 QPS 限制 |
关联限流 | 当前资源访问量受另一个资源访问量影响 |
链路限流 | 对相同资源在不同调用路径下设置不同的限流规则(需关闭统一 context) |
Warm Up | 适用于刚启动的系统,慢启动保护 |
排队等待 | 请求进入队列处理,防止短时间内系统被压垮 |
欢迎收藏、点赞👍、评论💬,如需更多微服务实践文章,欢迎关注我持续更新的专栏!
如需 .md
文件、配图打包或配套项目源码,请留言~