Sentinel就是分布式系统的流量防卫兵
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
官方文档:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
项目地址:https://github.com/alibaba/Sentinel
相同点:
1、为了保证集群大部分服务的可用性和可靠性,防止崩溃,牺牲小我
2、用户最终都是体验到某个功能不可用
不同点:
1、熔断是被调用方故障,触发的系统主动规则
2、降级是基于全局考虑,停止一些正常服务,释放资源
Sentinel 和 Hystrix 的原则是一致的: 当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。
熔断降级设计理念
在限制的手段上,Sentinel 和 Hystrix 采取了完全不一样的方法。Hystrix 通过 线程池隔离 的方式,来对依赖(在 Sentinel 的概念中对应 资源)进行了隔离。这样做的好处是资源和资源之间做到了最彻底的隔离。缺点是除了增加了线程切换的成本(过多的线程池导致线程数目过多),还需要预先给各个资源做线程池大小的分配。
Sentinel 对这个问题采取了两种手段:
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
使用 java -jar sentinel-dashboard-1.6.3.jar
启动sentinel
注:默认是8080端口,如果8080端口被占用,那么可以修改对应的端口号
java -jar sentinel-dashboard-1.6.3.jar --server.port=8333
作用就是将信息收集到控制台
# 控制台地址配置
spring.cloud.sentinel.transport.dashboard=127.0.0.1:8333
# 传输端口
spring.cloud.sentinel.transport.port=8719
1)每一个微服务都引入actuator信息审计模块依赖
在springboot模块添加此依赖,可以实时统计应用的健康状况信息,请求调用信息。sentinel可以获取到这些信息进行实时监控
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
2)暴露endpoint端口
#暴露所有端点
management.endpoints.web.exposure.include=*
1)新建配置类
@Configuration
public class GulimailSeckillSentinelConfig {
public GulimailSeckillSentinelConfig() {
WebCallbackManager.setUrlBlockHandler(new UrlBlockHandler() {
@Override
public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws IOException {
R error = R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(), BizCodeEnume.TO_MANY_REQUEST.getMsg());
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.getWriter().write(JSON.toJSONString(error));
}
});
}
}
2)进行全局配置
引入openfeign依赖
>
>org.springframework.cloud >
>spring-cloud-starter-openfeign >
>
引入sentinel依赖
<!--sentinel依赖-->
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
feign.sentinel.enabled=true
此时就可以检测到feign的远程调用
在@feignClient
注解中添加fallback回调方法
@FeignClient(value = "gulimail-seckill",fallback = SeckillFeignServiceFallBack.class)
添加回调实现类
@Component
@Slf4j
public class SeckillFeignServiceFallBack implements SeckillFeignService {
@Override
public R getSkuSeckillInfo(Long skuId) {
log.info("熔断方法调用。。。getSkuSeckillInfo");
return R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(),BizCodeEnume.TO_MANY_REQUEST.getMsg());
}
}
RT:超过1ms就会降级
时间窗口:在这10秒以内就不会调用此方法,等10秒过后继续尝试调用
远程服务被降级处理后,sentinel就不会调用远程服务了,默认触发熔断回调方法
优点:远程服务不停机,返回默认的熔断数据(限流后的数据)
缺点:超大流量浏览的时候,必须牺牲一些远程服务,远程服务指定降级规则后,此时不会运行自己的业务逻辑
1)使用try-catch的方式定义受保护的资源
try(Entry entry = SphU.entry("seckillSkus")) {
//业务逻辑
} catch (Exception e) {
log.error("资源被限流:{}",e.getMessage());
e.printStackTrace();
}
1)添加注解
@SentinelResource(value = "getCurrentSeckillSkusResource",blockHandler = "blockHandler")
2)blockHandler——指定降级后方法的回调
blockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
/**
* getCurrentSeckillSkus降级后的回调方法
* @return
*/
public List<SeckillSkuRedisTo> blockHandler(BlockException e){
log.error("getCurrentSeckillSkusResource资源被限流:{}",e.getMessage());
return null;
}
3)fallback——针对异常的回调
fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:
注:无论注解还是try-catch都需要配置被限流以后的默认返回,url请求可以设置统一返回:WebCallbackManager
https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81
Sentinel 1.6.0 引入了 Sentinel API Gateway Adapter Common 模块,此模块中包含网关限流的规则和自定义 API 的实体和管理逻辑:
其中网关限流规则 GatewayFlowRule 的字段解释如下:
用户可以通过 GatewayRuleManager.loadRules(rules) 手动加载网关规则,或通过 GatewayRuleManager.register2Property(property) 注册动态规则源动态推送(推荐方式)。
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-sentinel-gatewayartifactId>
<version>2.1.0.RELEASEversion>
dependency>
#回调的类型
spring.cloud.sentinel.scg.fallback.content-type=application/json
#指定回调的状态码
spring.cloud.sentinel.scg.fallback.response-status=400
添加配置类SentinelGatewayConfig
@Configuration
public class SentinelGatewayConfig {
public SentinelGatewayConfig() {
GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
//网关限流了请求,就会调用此回调
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
R error = R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(), BizCodeEnume.TO_MANY_REQUEST.getMsg());
String errorJson = JSON.toJSONString(error);
Mono<ServerResponse> body = ServerResponse.ok().body(Mono.just(errorJson), String.class);
return body;
}
});
}
}