Sentinel 是面向云原生微服务的流量监控,熔断降级组件。能够监控并保护你的微服务。
Sentinel中文文档
Sentinel 分为两个部分:
使用docker 安装sentinel:
docker pull bladex/sentinel-dashboard
docker run --name sentinel -d -p 8858:8858 -d bladex/sentinel-dashboard
Windows 下安装 sentinel
sentinel下载地址
通过命令java -jar 运行jar包
访问localhost:8080
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- springcloud alibaba 后续做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency> <!--引入自己定义的api通用包,可以使用payment支持Entity-->
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
#Nacos服务注册中心地址
server-addr: 114.55.56.149:8849
sentinel:
transport:
# 配置sentinel dashboard地址
dashboard: localhost:8080
# 默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
# clientIp: localhost
management:
endpoints:
web:
exposure:
include: '*'
注: 由于这里的项目启动和sentinel启动都是本地,所以无需配置ClientIp。如果是虚拟机中安装的Sentinel,则ClientIp需要配置成项目启动地址(即 cloudalibaba.sentinel.service8401 启动地址)。如果Sentinel无法监控项目,则需要排查Sentinel启动地址能否访问项目启动地址了。
package com.atguigu.springcloud.alibaba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class MainApp8401 {
public static void main(String[] args){
SpringApplication.run(MainApp8401.class,args);
}
}
package com.atguigu.springcloud.alibaba.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
return "-----testA";
}
@GetMapping("/testB")
public String testB(){
return "-----testB";
}
}
测试:由于sentinel使用的懒加载机制,所以无法看到监控到的数据。当我们访问Controller中的方法后,发现可以监控到我们的服务方法了。
测试:我们访问localhost:8041/testA,当我们每秒访问一次则可以正常访问,当超过一次则返回如下信息:
并发线程数:可以同时处理多个客户端发送过来的请求,超过了,则返回错误信息。
关联:当关联的资源达到阈值时,就限流自己。当与A关联的资源B达到阈值后,就限流A。
当管关联资源/testB的qps阈值超过1时,就限流/testA的Rest访问地址,当关联资源到达阈值后限制配置好的资源名。
比如我们实际开发中,订单下单后需要调用支付接口,当我们的支付接口到达极限要瘫了,就能 去限制订单下单的接口。
链路:只针对从指定链路访问到本资源的请求做统计,判断是否超过阈值。这篇文章有对链路详细介绍和测试。链路文章地址
测试: 我们将/testA设置为上图设置。然后疯狂请求/testA,发现开始的时候每秒请求超过3此后会返回默认的错误信息,五秒过后,就能正常的响应三次过后的请求了!
Sentinel 降级又称熔断降级。
降级策略有三个:
测试:
表示我们的/testD请求,必须在200ms秒内处理完请求,且请求数要小于等于五的,否则发生熔断。熔断后,再下一秒后(窗口时间),服务才恢复。然而在这一秒钟(时间窗口)内,服务是不可用的(熔断了)。
当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值之后,资源进入降级状态,即接下来的时间窗口之内,对这个方法的调用都会自动的返回。异常比率的阈值范围是 [0.0 , 1.0],代表0% - 100%。
表示/testD请求,如果每秒请求>=5,且异常率达到20%,则进行熔断。并且在接下来的三秒内访问都将自动返回。三秒后熔断关闭,访问正常。
当资源近1分钟的异常数且超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若timeWindow小于60s,则结束熔断状态后仍可能在进入熔断状态。
时间窗口一定要大于等于60秒。
表示请求/testE,一分钟类出现5次异常,则发生熔断,而后70秒内都无法在访问,会自动返回。70秒后熔断关闭,恢复访问。
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的Top K 数据,并对其访问进行限制。比如:
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅包含任店参数的资源调用生效。
之前学习的Hystrix,当某个方法出现问题了,就能找到对应的兜底降级方法,而Sentinel 有一套默认的兜底方法返回:Blocked by Sentinel (flow limiting)那么Sentinel如何自定义兜底方法呢?
Hystrix 自定义兜底方法是用的注解 @HystrixCommand 。Sentinel 使用的是 @SentinelResource 。
代码
/**
*
* @SentinelResource(value = "testHotKey" ,blockHandler = "deal_testHotkey") 这里的testHotKey是可以随便取的。只要是唯一标识就可以
* blockHandler = "deal_testHotkey" 表示如果违背了sentinel的配置规则有方法deal_testHotkey进行处理。
*
* @param p1
* @param p2
* @return
*/
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey" ,blockHandler = "deal_testHotkey")
public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
@RequestParam(value = "p2", required = false) String p2){
return "-----testHotKey";
}
public String deal_testHotkey(String p1, String p2, BlockException e){
//sentinel 系统的默认提示: Blocked by sentinel (flow limiting)
return "------deal_testHotkey, o(╥﹏╥)o";
}
测试效果:当p1一直等于a且每秒访问超过一次后,再次访问,则返回我们自定义的方法:
上述按理演示了第一个参数p1,当QPS超过了1秒1次点击后马上被限流。我们期望p1参数当它是某个特殊值时,他的限流值和平时不一样,加入当p1的值等于5时,他的阈值可以达到200。
总结:
@SentinelResource 处理的是Sentinel控制台配置的违规情况,有blockHandle方法配置的兜底处理。
但是运行时报错是不处理的,即RuntimeException。如 int age = 1/0,这个是java运行时报出的运行异常RuntimeException,@SentinelResource 不管。
package com.atguigu.springcloud.alibaba.myhandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.entities.CommonResult;
public class CustomerBlockHandler {
public static CommonResult handlerException(BlockException exception){
return new CommonResult(4444,"按客户自定义,global handlerException -----1");
}
public static CommonResult handlerException2(BlockException exception){
return new CommonResult(4444,"按客户自定义,global handlerException -----2");
}
}
controller层配置我们的处理类
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",blockHandlerClass = CustomerBlockHandler.class,blockHandler = "handlerException2")
public CommonResult customerBlockHandler(){
return new CommonResult(200,"按客户自定义",
new Payment(2020L,"serial003"));
}
他们的关系如下:
sentinel 主要有三个核心Api(了解即可)
每次我们项目重启,Sentinel里面的配置内容就会消失。那么如何解决实现持久化呢?