• Sentinel的简单介绍和使用


    1 基础概念

    熔断A 服务调用 B 服务的某个功能,由于网络不稳定问题,或者 B 服务卡机,导致功能时间超长。如果这样子的次数太多,就可以直接将 B 断路了(A 不再请求 B 接口),凡是调用 B 的直接返回降级数据,不必等待 B 的超长执行。 这样 B 的故障问题,就不会级联影响到 A

    降级:整个网站处于流量高峰期,服务器压力剧增,根据当前业务情况及流量,对一些服务和页面进行有策略的降级[停止服务,所有的调用直接返回降级数据]。以此缓解服务器资源的的压力,以保证核心业务的正常运行,同时也保持了客户和大部分客户的得到正确的相应。
    限流:对打入服务的请求流量进行控制,使服务能够承担不超过自己能力的流量压力。
    2.Sentinel
    随着微服务的流行,服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
    资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。
    只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来 。大部分情况下,可以使用方法签名,URL ,甚至服务名称作为资源名来标示资源。
    围绕资源的实时状态设定的规则,可以包括 流量控制规则 熔断降级规则 以及 系统保护规 。所有规则可以动态实时调整。
    当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败, 避免影响到其它的资源而导致级联故障。
    3.熔断降级设计理念
    通过并发线程数进行限制:
    Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
    通过响应时间对资源进行降级:
    除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。
    4.SpringBoot集成Sentinel
    加入依赖:
    1. <dependency>
    2. <groupId>com.alibaba.cloud</groupId>
    3. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    4. </dependency>

    根据依赖版本下载相应的

    sentinel-dashboard-1.6.3.jarhttps://github.com/alibaba/Sentinel/releases/download/1.6.3/sentinel-dashboard-1.6.3.jarReleases · alibaba/Sentinel · GitHub

     然后使用命令台启动(server.port指端口,自行填写):

    java -jar sentinel-dashboard-1.6.3.jar --server.port=8333

    然后输入http://localhost:8333/  即可看到页面

    初始账号密码都是sentinel

    配置文件中加入:

    1. spring.cloud.sentinel.transport.dashboard=localhost:8333
    2. spring.cloud.sentinel.transport.port=8719

    =======================================================================

    限流 

    启动项目,随便访问一个API

    新增流控规则(每秒请求数为1):

    可以看到出现了流控规则:

     疯狂刷新页面,就会出现:

     限流成功了

    为了得到更多信息,对外暴露endpoint

    在pom中导入:

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-actuator</artifactId>
    4. </dependency>

    配置文件中加入:

    management.endpoints.web.exposure.include=*

     重启项目,疯狂刷新刚刚的接口,就可以在实时监控中看到:

     接下来自定义流量控制显示的内容(显示内容自定):

    1. @Configuration
    2. public class SeckillSentinelConfig {
    3. public SeckillSentinelConfig() {
    4. WebCallbackManager.setUrlBlockHandler(new UrlBlockHandler() {
    5. @Override
    6. public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws IOException {
    7. R error = R.error(BizCodeEnum.TO_MANY_REQUEST.getCode(), BizCodeEnum.TO_MANY_REQUEST.getMessage());
    8. response.setCharacterEncoding("UTF-8");
    9. response.setContentType("application/json");
    10. response.getWriter().write(JSON.toJSONString(error));
    11. }
    12. });
    13. }
    14. }

    因为流控规则保存在内存中,重启项目会消失,所以需要重新添加流控规则。再次重新刷新页面,就会出现自定义的显示内容了:

     流控模式说明:

     关联:对资源A的限流,是关联资源B流量大时才会触发

    链路:对资源A的限流,是只有经过入口资源B时才触发,直接访问资源A是不触发的

    流控效果说明:

     Warm Up:经过10秒阈值会升到100

     排队等待:多出来的访问请求超过3秒才失效,之前是一直等待

    =======================================================================

    熔断降级

    在需要用到sentinel的所有微服务里都加入sentinel依赖和actuator依赖,并配置:

    1. spring.cloud.sentinel.transport.dashboard=localhost:8333
    2. management.endpoints.web.exposure.include=*
    3. feign.sentinel.enabled=true

    比如我的product服务调用seckill服务的接口,

     则在定义feign的时候可以指定fallback内容:

    1. @FeignClient(value = "gulimall-seckill",fallback = SeckillFeignServiceFallBack.class)
    2. public interface SeckillFeignService {
    3. /**
    4. * 根据skuId查询商品是否参加秒杀活动
    5. * @param skuId
    6. * @return
    7. */
    8. @GetMapping(value = "/sku/seckill/{skuId}")
    9. R getSkuSeckilInfo(@PathVariable("skuId") Long skuId);
    10. }

    指定了fallback为SeckillFeignServiceFallBack(返回内容自定)

    1. @Slf4j
    2. @Component
    3. public class SeckillFeignServiceFallBack implements SeckillFeignService {
    4. @Override
    5. public R getSkuSeckilInfo(Long skuId) {
    6. log.info("熔断");
    7. return R.error(BizCodeEnum.TO_MANY_REQUEST.getCode(),BizCodeEnum.TO_MANY_REQUEST.getMessage());
    8. }
    9. }

    停止seckill服务,访问product服务,可以看到日志平台提示熔断。

    对seckill服务点击降级按钮:

    RT: 当进入的请求的响应时间超过了1000毫秒,则实施熔断,10秒后检查若还是这样就继续熔断,否则结束熔断。

    当访问量超大时,需要对一些服务做出服务,可直接让远程服务本身指定降级策略,这样虽然远程服务依然在运行,但运行是默认返回降级策略。

    自定义一个叫“seckillSkus”的资源:

    1. @Override
    2. public List getCurrentSeckillSkus() {
    3. try (Entry entry = SphU.entry("seckillSkus")) {
    4. //业务
    5. } catch (BlockException e) {
    6. log.error("资源被限流{}",e.getMessage());
    7. }
    8. return null;
    9. }

    接着就可以利用这个资源名进行流控或者熔断降级了。

    以上是使用代码的形式,优点为较为灵活。

    然后就是以注解的形式:

    @SentinelResource(value = "getCurrentSeckillSkusResource",blockHandler = "blockHandler")

    因为指定了blockHandler,所以还要写一个blockHandler出来

    1. public List<SeckillSkuRedisTo> blockHandler(BlockException e) {
    2. log.error("getCurrentSeckillSkusResource被限流了,{}",e.getMessage());
    3. return null;
    4. }

    效果是一样的,自定了一个叫getCurrentSeckillSkusResource的资源

    ========================================================================

    网关层配置sentinel

    除了上述所需导入的依赖和配置,还需要在网关模块加入以下的依赖:

    1. <dependency>
    2. <groupId>com.alibaba.cloud</groupId>
    3. <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
    4. </dependency>

    为了看到新效果,需要使用1.7以上的版本,所以重新下载一个1.7以上的sentinel-dashboard-1.7.1.jar。然后启动服务,可以看到网关和其它的不同之处:

    可以看到网关出现在了请求链路里:

    对秒杀服务的网管进行配置:

     

    其中Burst Size代表忽然流量暴增时额外增加的请求数 

     通过api管理可以同时管理多个api

    还可以通过配置文件定制返回结果:

    1. spring.cloud.sentinel.scg.fallback.content-type=application/json
    2. spring.cloud.sentinel.scg.fallback.response-status=400
    3. spring.cloud.sentinel.scg.fallback.response-body=wrong

     或者写代码来配置:

    1. import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
    2. import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
    3. import com.alibaba.fastjson.JSON;
    4. import com.atguigu.common.exception.BizCodeEnum;
    5. import com.atguigu.common.utils.R;
    6. import org.springframework.context.annotation.Configuration;
    7. import org.springframework.web.reactive.function.server.ServerResponse;
    8. import org.springframework.web.server.ServerWebExchange;
    9. import reactor.core.publisher.Mono;
    10. @Configuration
    11. public class SentinelGatewayConfig {
    12. public SentinelGatewayConfig() {
    13. GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
    14. //网关限流了请求,就会调用此回调
    15. @Override
    16. public Mono handleRequest(ServerWebExchange exchange, Throwable t) {
    17. R error = R.error(BizCodeEnum.TO_MANY_REQUEST.getCode(), BizCodeEnum.TO_MANY_REQUEST.getMessage());
    18. String errorJson = JSON.toJSONString(error);
    19. Mono body = ServerResponse.ok().body(Mono.just(errorJson), String.class);
    20. return body;
    21. }
    22. });
    23. }
    24. }

     

  • 相关阅读:
    【嵌入式C】栈内存与printf,代码正确运行,删掉 printf 代码就崩溃了??
    初识面相对象深入理解、构造方法--学习JavaEE的day12
    【Leetcode】1196. How Many Apples Can You Put into the Basket
    闪电藤文件传输助手上线
    2023年8月京东户外鞋服市场(京东数据运营)
    Eclipse初步学习使用
    java开发中postgresql数组字段类型处理
    vscode启动不了,折腾了半天发现已经不支持win7
    ​最新Xcode9 无证书真机调试流程
    10个微服务设计模式
  • 原文地址:https://blog.csdn.net/xushuai2333333/article/details/127565735