Spring Cloud Alibaba 03_使用 Sentinel 实现服务限流降级熔断
雪崩效应
当服务A不可用时,服务B调用服务A的所有线程将处于阻塞状态,在高并发情况下,服务B中阻塞的线程越来越多,导致内存空间不足,致使服务B崩溃,同理,需要调用服务B的服务C也可能崩溃,这就是雪崩效应。
解决方案:
降级: 系统将某些非必要功能关闭,只提供关键功能
限流: 只接收系统能够承载的访问量
熔断: 切断对某个故障服务的调用
Sentinel 实现服务限流
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
application:
name: provider
server:
port: 8083
# 暴露所有端点
management:
endpoints:
web:
exposure:
include: '*'
阈值类型选择QPS,单机阈值设为1
即每秒钟只允许1次访问
同时观察到以下图表:
流控模式-关联模式
此时当 /list 接口每秒访问超过1次时,/index 接口将会被限流(你闯祸我背锅)
流控模式-链路模式
在 provider 中添加以下两个依赖:
<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>
在配置文件中配置关闭 sentinel 的 filter 功能:
spring:
cloud:
sentinel:
filter:
enabled: false
FilterConfiguration 配置类:
package com.blu.configuration;
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@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;
}
}
在Service层添加test方法,并加上 @SentinelResource 注解:
package com.blu.service;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;
@Service
public class ProviderService {
@SentinelResource("service-test")
public void test(){
System.out.println("test");
}
}
在 Controller 层添加 test1和test2两个方法来调用Service层的test方法:
@Autowired
private ProviderService providerService;
@GetMapping("/test1")
public String test1(){
this.providerService.test();
return "test1";
}
@GetMapping("/test2")
public String test2(){
this.providerService.test();
return "test2";
}
依次启动nacos、sentinel、 provider 后,设置以下流控规则:
频繁访问 /test1 接口,当QPS大于1时,将显示错误页面:
而频繁访问 /test2 接口皆正常:
流控效果 - Warm Up(预热)
添加如下流控规则:
当点击新增后,系统会在10s内缓慢地将 /index 接口的请求阈值升至3 QPS
流控效果-排队等待
服务降级-降级策略-RT
当某个请求的响应时间超过1毫秒时,将进入准降级状态,在接下来的1s时间内如果连续5个请求的响应时间均超过1毫秒,将进入降级状态,持续时间为10秒
服务降级-降级策略-异常比例
当请求出现异常的比例达到了20%,将进入降级状态,持续时间10s
服务降级-降级策略-异常数
在1分钟内异常请求的次数达到5个,将进入降级状态,持续时间80秒(这里的降级持续时间一定要大于1分钟!)
热点规则
在Controller中添加如下方法:
@GetMapping("/hot")
@SentinelResource("controller-hot")
public String hot(@RequestParam(value = "num1",required = false) Integer num1, @RequestParam(value = "num2",required = false) Integer num2){
return num1+"---"+num2;
}
请求示例:http://localhost:8081/hot?num1=1&num2=2
给 controller-hot 添加热点规则:
当请求参数中存在参数1(num1)时,QPS超过1将抛出异常:
在高级选项中,可设置参数例外值:
即:对参数1(num1)进行限流,阈值为1,但当num1为int类型,值为10时,限流阈值为1000
授权规则
package com.blu.configuration;
import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
public class RequestOriginParserDefinition implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest httpServletRequest) {
String name = httpServletRequest.getParameter("name");
if (StringUtils.isEmpty(name)){
throw new RuntimeException("name is null");
}
return name;
}
}
package com.blu.configuration;
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Configuration
public class SentinelConfiguration {
@PostConstruct
public void init(){
WebCallbackManager.setRequestOriginParser(new RequestOriginParserDefinition());
}
}
此时,访问不携带name参数将报错:
此时,访问 /index 接口必须携带name参数,且参数值必须为admin
此时,访问 /index 接口必须携带name参数,且参数值不能为blu
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blucoding.blog.csdn.net/article/details/109181318
内容来源于网络,如有侵权,请联系作者删除!