目录
一、概览
SpringCloudGateway是一个基于SpringBoot2.x的API网关,它可以帮助实现路由、过滤、容错等功能,同时也是微服务架构中不可或缺的一部分。在这篇博客中,将会了解到如何使用Sentinel实现SpringCloudGateway的限流、熔断降级。
Sentinel是一个轻量级的流量控制框架,它可以帮助我们实现熔断降级、限流等功能,同时也可以与SpringCloudGateway无缝集成。通过使用Sentinel,可以有效地保护微服务架构免受故障和异常的影响。
二、安装Sentinel
官方提供了UI控制台,下载地址:https://github.com/alibaba/Sentinel/releases
将下载好的jar包放到任意非中文路径目录,使用java命令启动,可以修改Sentinel的默认端口、账户、密码;server.port默认8080,sentinel.dashboard.auth.username默认sentinel,sentinel.dashboard.auth.password默认sentinel。
比如我这里放到D盘的Jar文件夹,启动时换成2500端口,命令如下:
java -Dserver.port=25000 -jar D:\Jar\sentinel-dashboard-1.8.2.jar
启动之后访问:http://localhost:25000/,账户密码都是sentinel,第一次启动后界面是空白的,因为还没有进行相关微服务项目的整合。
三、微服务整合sentinel
SpringCloudGateWay项目参考:SpringCloudGateway--自动路由映射与手动路由映射_雨欲语的博客-CSDN博客,源码下载地址:
GitHub - dengyifanlittle/littledyf-test: my-test
添加依赖:
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2020.0.RC1</version>
</dependency>
添加配置文件:
spring:
cloud:
sentinel:
transport:
# 服务监控端口
dashboard: localhost:25000
# 默认 8719,如果8719被占用了会自动从 8719 开始依次 +1 扫描,直至找到未被占用的端口
port: 8719
四、限流
启动项目,访问:http://localhost:9999/service/nacos/test,这时再刷新sentinel界面,里面便有数据了
流控规则页面新增:
1、流控模式
①直接
新增流控规则,流控模式选择直接模式,阈值类型QPS,单机阈值1:
使用jemeter进行测试,线程数量、现成启动时间、运行次数分别设置为1、1、4:
可以看到有一个成功,三个失败,且失败信息是sentinel默认:
删除原有规则,新增流控规则,流控模式选直接,阈值类型选择并发线程数,单机阈值设置为2,微服务中只启动一个service即可,并修改其中代码:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author dengyifan
* @create 2023/11/1 17:02
* @description
*/
@RestController
@RequestMapping("/nacos")
public class NacosTestController {
@GetMapping("/test")
public String test() throws InterruptedException {
Thread.sleep(2000);
return "8088";
}
}
并发线程数表示1秒内访问该API接口的线程数,当排队的线程数达到设定的阈值的时候就会进行限流操作,这种通常是出现在访问接口响应很慢的时候,因此代码里面主动休眠2秒模拟。jmeter模拟测试时线程数设置为10,其余为1:
可以看到返回结果中成功两次,其余8次失败,并返回sentinel默认错误信息:
如果将sentinel的流控规则删除,则全部成功:
②关联
新增流控规则,流控模式选择关联,阈值类型选择QPS,单机阈值设置为2,关联资源填写另外的访问接口:
在我们的微服务中新增两个接口:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author dengyifan
* @create 2023/11/1 17:02
* @description
*/
@RestController
@RequestMapping("/nacos")
public class NacosTestController {
@GetMapping("/test-one")
public String testOne() {
return "8088-one";
}
@GetMapping("/test-two")
public String testTwo() {
return "8088-two";
}
}
在jmeter中线程组设置为1、1、10:
设置两个http请求,分别设置为test-one和test-two:
启动测试,可以发现模拟test-one的接口两个成功,8个失败,模拟test-two的接口10个全部成功,因为设置了关联模式,并且test-one关联了test-two接口,当test-two接口的访问超过2的时候,就会让test-one的处于失败状态。这种:
③链路
对于链路模式,比如A路径会访问到资源C,B路径也会访问到资源C,此时配置链路模式,入口资源设置为A,当访问A达到一定限制就会触发限流,B没有配置,则不会触发。
配置文件增加:
sentinel.web-context-unify=false
在gateway项目中新建Controller和Service:
import com.littledyf.service.SentinelTestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author dengyifan
* @create 2023/11/9 10:41
* @description
*/
@RestController
@RequestMapping("/test")
public class SentinelTestController {
@Autowired
private SentinelTestService sentinelTestService;
@GetMapping("/test-sentinel")
public String testSentinel() {
return sentinelTestService.testSentinel();
}
}
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;
/**
* @Author dengyifan
* @create 2023/11/9 10:42
* @description
*/
@Service
public class SentinelTestService {
@SentinelResource("sentinel")
public String testSentinel() {
return "test sentinel";
}
}
其中@SentinelResource("sentinel")是手动设置资源名,sentinel只会扫描controller层的资源,service通过注解设置。
新增链路流控:
jmeter添加测试:
启动测试查看结果可发现4次里面3次失败:
2、流控效果
①快速失败
之前流控模式都是使用快速失败,即直接失败,抛出异常。
②Warm Up
warm up是指预热,比如一些秒杀环节,之前系统流量不高,当秒杀开启突然升高,这个时候开启预热模式,让通过的流量缓慢增加,能够达到设定阈值为止,这样能够很好的保护系统。
其中会有一个默认1的coldFactor,该值为3,请求QPS从threshold/3开始,经过设置的预热时间后达到设定的阈值,比如我们现在进行以下设置:
即刚开始有5/3个,后面经过3秒后达到设定的阈值5。
jmeter设置:
启动后可以看到前几秒都有失败的,经过3秒后,就稳定达到5个成功:
③排队等待
排队等待即让请求均匀通过,其实跟漏桶算法是对应的,选择排队等待,必须要将类型设置为QPS,否则是无效的:
jmeter设置:
效果:
五、熔断降级
新增熔断规则界面:
1、慢调用比例
为了模拟慢调用,在接口中进行1000毫秒的休眠达到响应慢的作用:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author dengyifan
* @create 2023/11/1 17:02
* @description
*/
@RestController
@RequestMapping("/nacos")
public class NacosTestController {
@GetMapping("/test")
public String test() throws InterruptedException {
Thread.sleep(1000);
return "8088";
}
}
熔断设置:
jmeter设置:
结果:
刚运行完之后,在5秒内继续运行,可以看到结果都是失败状态,都被熔断处理了。
2、异常比例
代码修改成会出现异常的情况:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author dengyifan
* @create 2023/11/1 17:02
* @description
*/
@RestController
@RequestMapping("/nacos")
public class NacosTestController {
@GetMapping("/test")
public String test() throws Exception {
String s = null;
if (s.equals("1")){
return "1";
}
return "8088";
}
}
新增熔断规则,熔断策略选择异常比例:
jmeter设置不变,其中前5个都会抛出空指针异常,后面5个是直接熔断:
3、异常数
熔断策略选择异常数跟异常比例类似,只是异常比例变为异常数了而已
sentinel还可以配置热点规则以及系统自适应限流。热点规则就类似于微博热搜一样,有时候突然一个热点访问量大,这时候可以进行限流设置,很多时候热点都会进行相应的缓存,比如加上一级缓存、二级缓存等,这些实际就是为了保护系统而进行的设置。