文章目录
- 一、Sentinel 介绍
- 同类组件功能对比
- 二、Sentinel 快速入门
- 2.1 获取控制台jar包
- 2.2 启动控制台
- 2.3 添加服务端
- 三、流控配置
- 3.1 快速入门
- 3.2 BlockException统一处理
- 3.3 配置讲解
一、Sentinel 介绍
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel 具有以下特征:
- 丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。
- 完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
- 广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
- 完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展点。您可以通过实现扩展点,快速的定制逻辑。例如定制规则管理、适配数据源等。
同类组件功能对比
Sentinel | Hystrix | resilience4j | |
隔离策略 | 信号量隔离(并发控制) | 线程池隔离/信号量隔离 | 信号量隔离 |
熔断降级策略 | 基于慢调用比例、异常比例、异常数 | 基于异常比例 | 基于异常比例、响应时间 |
实时统计实现 | 滑动窗口(LeapArray) | 滑动窗口(基于 RxJava) | Ring Bit Buffer |
动态规则配置 | 支持近十种动态数据源 | 支持多种数据源 | 有限支持 |
扩展性 | 多个扩展点 | 插件的形式 | 接口的形式 |
基于注解的支持 | 支持 | 支持 | 支持 |
单机限流 | 基于 QPS,支持基于调用关系的限流 | 有限的支持 | Rate Limiter |
集群流控 | 支持 | 不支持 | 不支持 |
流量整形 | 支持预热模式与匀速排队控制效果 | 不支持 | 简单的 Rate Limiter 模式 |
系统自适应保护 | 支持 | 不支持 | 不支持 |
热点识别/防护 | 支持 | 不支持 | 不支持 |
多语言支持 | Java/Go/C++ | Java | Java |
Service Mesh 支持 | 支持 Envoy/Istio | 不支持 | 不支持 |
控制台 | 提供开箱即用的控制台,可配置规则、实时监控、机器发现等 | 简单的监控查看 | 不提供控制台,可对接其它监控系统 |
二、Sentinel 快速入门
Sentinel 控制台提供一个轻量级的控制台,它提供机器发现、单机资源实时监控、集群资源汇总,以及规则管理的功能。您只需要对应用进行简单的配置,就可以使用这些功能。
2.1 获取控制台jar包
可以从 release 页面 下载对应版本的控制台 jar 包。这里下载的是1.8.3版本
2.2 启动控制台
Sentinel 控制台是一个标准的 Spring Boot 应用,以 Spring Boot 的方式运行 jar 包即可。
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
如若8080端口冲突,可使用 -Dserver.port=新端口
进行设置。
从 Sentinel 1.6.0 起,Sentinel 控制台引入基本的登录功能,默认用户名和密码都是 sentinel
。可以参考 鉴权模块文档 配置用户名和密码。
这里启动后我们就可以直接查看地址:http://127.0.0.1:8080登录了,当然现在登录的话是没有任何信息的,需要启动我们的服务,并且有访问才行。
2.3 添加服务端
2.3.1 添加依赖
<!-- sentinel流控组件 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.3.2 添加配置
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8080
这时候我们访问127.0.0.1:8010/order/add接口后就可以看到控制台有信息了
三、流控配置
3.1 快速入门
我们可以直接在控制台配置,先访问接口,然后直接针对接口进行配置,位置如下:
我们可以设置按照QPS或并发线程数来进行流控,我们只要新增就会立即生效。这时候失败了会给我们返回默认的流控信息
Blocked by Sentinel (flow limiting)
当然我们也可以在代码中进行定制该接口的流控处理:
@RestController
@RequestMapping("/order")
public class OrderController {
@GetMapping("/add")
@SentinelResource(value = "add", blockHandler = "addBlockHandle")
public String add() {
return "添加商品成功.";
}
public String addBlockHandle(BlockException blockException) {
blockException.printStackTrace();
return "添加商品接口已经被流控了";
}
}
如上所示,我们只需要在我们所在的资源上添加 @SentinelResource
注解,添加志愿名和流控后的处理方法,然后写一个流控的处理方法就行了。这里需要注意的事,我们这里的sentinel是没有持久化的,所以每次服务重启之前配置的流控规则都是会没有,需要重新配置才可以生效。
3.2 BlockException统一处理
因为我们一般资源接口很多,避免在每个资源上去添加注解@SentinelResource
,而且返回类型一般都是一个统一的类型Result,所以我们可以统一处理。
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.alibaba.nacos.common.http.param.MediaType;
import com.alibaba.order.common.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
@Slf4j
public class SentinelBlockExceptionHandle implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
log.info("流控规则:{}", e.getRule());
Result result = null;
if (e instanceof FlowException) {
result = Result.error(100101, "服务流控了");
} else if (e instanceof DegradeException) {
result = Result.error(100102, "服务降级了");
} else if (e instanceof ParamFlowException) {
result = Result.error(100103, "服务热点参数限流了");
} else if (e instanceof SystemBlockException) {
result = Result.error(100104, "触发系统保护规则了");
} else if (e instanceof AuthorityException) {
result = Result.error(100105, "授权不通过");
}
httpServletResponse.setStatus(500);
httpServletResponse.setCharacterEncoding("utf-8");
httpServletResponse.setContentType(MediaType.APPLICATION_JSON);
new ObjectMapper().writeValue(httpServletResponse.getWriter(), result);
}
}
这里只是举例的,我们可以自己根据业务来进行开发。
3.3 配置讲解
在流控配置中有如下配置:资源名、针对来源、阈值类型、单机阈值、是否集群、流控模式、流控效果
资源名:唯一名称,默认请求路径
针对来源:Sentinel可以针对调用者进行限流,填写微服务名,指定对哪个微服务进行限流 ,默认default(不区分来源,全部限制)
阀值类型:有QPS和并发线程数两种模式,
- QPS就是每秒类的请求次数;
- 并发数是当前有多少线程在处理请求。
单机阈值:该配置在没有勾选集群的时候就是单机的阈值,就是对应QPS的数量,就是每秒请求数量的阈值;或者对应并发数的阈值。
流控模式:
- 直接指的是当前资源达到上面设置的阈值时就直接对当前资源进行流控;
- 关联指的是当关联的资源达到上面设置的阈值时,当前资源进行流控;
- 链路指的是当前资源达到上面设置的阈值时,入口资源被流控;
流控效果:
- 快速失败指的是当达到阈值时直接失败拒绝;
- Warm Up指的是在指定时间内预热,慢慢的接受请求达到阈值;
- 排队等待指的是流控后在超时时间内进行等待;
是否集群:当选择集群后,阈值就可以选择是总值的还是单机均摊值。
注意事项:
- 当我们使用了
@SentinelResource
注解后,该注解的资源就不在使用BlockException的统一处理 - 当我们流控模式使用链路的时候,需要在yml配置文件中添加配置
spring.cloud.sentinel.web-context-unify=false
---