• Sentinel整合


    RestTemplate整合Sentinel

    Spring Cloud Alibaba Sentinel 支持对 RestTemplate 的服务调用使用 Sentinel 进行保护,在构造 RestTemplate bean的时候需要加上 @SentinelRestTemplate 注解。 @SentinelRestTemplate 注解的属性支持限流(blockHandler, blockHandlerClass) 和降级(fallback, fallbackClass)的处理。

    引入依赖

    1. com.alibaba.cloud
    2. spring-cloud-alibaba-nacos-discovery
    3. org.springframework.cloud
    4. spring-cloud-starter-netflix-ribbon
    5. com.alibaba.cloud
    6. spring-cloud-starter-alibaba-sentinel
    7. org.springframework.boot
    8. spring-boot-starter-actuator

    @SentinelRestTemplate注解

    1. @Bean
    2. @LoadBalanced
    3. @SentinelRestTemplate(
    4. blockHandler = "handleException",blockHandlerClass = GlobalExceptionHandler.class,
    5. fallback = "fallback",fallbackClass = GlobalExceptionHandler.class
    6. )
    7. public RestTemplate restTemplate() {
    8. return new RestTemplate();
    9. }

    降级的异常处理类

    1. @RequestMapping(value = "/findOrderByUserId/{id}")
    2. public R findOrderByUserId(@PathVariable("id") Integer id) {
    3. //ribbon实现
    4. String url = "http://mall-order/order/findOrderByUserId/"+id;
    5. R result = restTemplate.getForObject(url,R.class);
    6. return result;
    7. }
    8. //全局的异常处理工具类
    9. public class GlobalExceptionUtil {
    10. /**
    11. * 注意: static修饰,参数类型不能出错
    12. * @param request org.springframework.http.HttpRequest
    13. * @param body
    14. * @param execution
    15. * @param ex
    16. * @return
    17. */
    18. public static SentinelClientHttpResponse handleException(HttpRequest request,
    19. byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
    20. R r = R.error(-1, "===被限流啦===");
    21. try {
    22. return new SentinelClientHttpResponse(new ObjectMapper().writeValueAsString(r));
    23. } catch (JsonProcessingException e) {
    24. e.printStackTrace();
    25. }
    26. return null;
    27. }
    28. public static SentinelClientHttpResponse fallback(HttpRequest request,
    29. byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
    30. R r = R.error(-2, "===被异常降级啦===");
    31. try {
    32. return new SentinelClientHttpResponse(new ObjectMapper().writeValueAsString(r));
    33. } catch (JsonProcessingException e) {
    34. e.printStackTrace();
    35. }
    36. return null;
    37. }
    38. }

    yml配置

    1. server:
    2. port: 8801
    3. spring:
    4. application:
    5. name: mall-user-sentinel-ribbon-demo #微服务名称
    6. #配置nacos注册中心地址
    7. cloud:
    8. nacos:
    9. discovery:
    10. server-addr: 127.0.0.1:8848
    11. sentinel:
    12. transport:
    13. # 添加sentinel的控制台地址
    14. dashboard: 127.0.0.1:8080
    15. # 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
    16. port: 8719
    17. #暴露actuator端点 http://localhost:8800/actuator/sentinel
    18. management:
    19. endpoints:
    20. web:
    21. exposure:
    22. include: '*'
    23. #true开启sentinel对resttemplate的支持,false则关闭 默认true
    24. resttemplate:
    25. sentinel:
    26. enabled: true

    Sentinel RestTemplate 限流的资源规则提供两种粒度:

    • httpmethod:schema://host:port/path:协议、主机、端口和路径
    • httpmethod:schema://host:port:协议、主机和端口

    OpenFeign整合Sentinel

    Sentinel 适配了 Feign 组件。如果想使用,除了引入 spring-cloud-starter-alibaba-sentinel 的依赖外还需要 2 个步骤:

    1.配置文件打开 Sentinel 对 Feign 的支持:

    feign.sentinel.enabled=true

    2.加入 spring-cloud-starter-openfeign 依赖使 Sentinel starter 中的自动化配置类生效:

    1. <dependency>
    2. <groupId>org.springframework.cloudgroupId>
    3. <artifactId>spring-cloud-starter-openfeignartifactId>
    4. dependency>

    使用

    在Feign的声明式接口上添加fallback属性

    1. @FeignClient(value = "mall-order",path = "/order",fallback = FallbackOrderFeignService .class)
    2. public interface OrderFeignService {
    3. @RequestMapping("/findOrderByUserId/{userId}")
    4. public R findOrderByUserId(@PathVariable("userId") Integer userId);
    5. }
    6. @Component //必须交给spring 管理
    7. public class FallbackOrderFeignService implements OrderFeignService {
    8. @Override
    9. public R findOrderByUserId(Integer userId) {
    10. return R.error(-1,"=======服务降级了========");
    11. }
    12. }

    添加fallbackFactory属性

    1. @Component
    2. public class FallbackOrderFeignServiceFactory implements FallbackFactory {
    3. @Override
    4. public OrderFeignService create(Throwable throwable) {
    5. return new OrderFeignService() {
    6. @Override
    7. public R findOrderByUserId(Integer userId) {
    8. return R.error(-1,"=======服务降级了========");
    9. }
    10. };
    11. }
    12. }

    cotroller

    1. @Autowired
    2. OrderFeignService orderFeignService;
    3. @RequestMapping(value = "/findOrderByUserId/{id}")
    4. public R findOrderByUserId(@PathVariable("id") Integer id) {
    5. //feign调用
    6. R result = orderFeignService.findOrderByUserId(id);
    7. return result;
    8. }

    注意:主启动类上加上@EnableFeignClients注解,开启Feign支持

    Sentinel整合Dubbo实战

    Sentinel 提供 Dubbo 的相关适配 Sentinel Dubbo Adapter,主要包括针对 Service Provider 和 Service Consumer 实现的 Filter。相关模块:

    • sentinel-apache-dubbo-adapter(兼容 Apache Dubbo 2.7.x 及以上版本,自 Sentinel 1.5.1 开始支持)
    • sentinel-dubbo-adapter(兼容 Dubbo 2.6.x 版本)

    引入此依赖后,Dubbo 的服务接口和方法(包括调用端和服务端)就会成为 Sentinel 中的资源,在配置了规则后就可以自动享受到Sentinel 的防护能力。

    Sentinel Dubbo Adapter 还支持配置全局的 fallback 函数,可以在 Dubbo 服务被限流/降级/负载保护的时候进行相应的 fallback 处理。用户只需要实现自定义的 DubboFallback 接口,并通过 DubboAdapterGlobalConfig注册即可。默认情况会直接将 BlockException 包装后抛出。同时,我们还可以配合 Dubbo 的 fallback 机制 来为降级的服务提供替代的实现。

    Provider端

    对服务提供方的流量控制可分为服务提供方的自我保护能力和服务提供方对服务消费方的请求分配能力两个维度。

    Provider 用于向外界提供服务,处理各个消费者的调用请求。为了保护 Provider 不被激增的流量拖垮影响稳定性,可以给 Provider 配置 QPS 模式的限流,这样当每秒的请求量超过设定的阈值时会自动拒绝多的请求。限流粒度可以是 服务接口 和 服务方法 两种粒度。若希望整个服务接口的 QPS 不超过一定数值,则可以为对应服务接口资源(resourceName 为接口全限定名)配置 QPS 阈值;若希望服务的某个方法的 QPS 不超过一定数值,则可以为对应服务方法资源(resourceName 为接口全限定名:方法签名)配置 QPS 阈值。

    限流粒度可以是服务接口和服务方法两种粒度:

    • 服务接口:resourceName 为 接口全限定名,如 com.tuling.mall.service.UserService
    • 服务方法:resourceName 为 接口全限定名:方法签名,如 com.tuling.mall.service.UserService:getById(java.lang.Integer)

    Consumer端

    对服务提供方的流量控制可分为控制并发线程数和服务降级两个维度。

    控制并发线程数

    Service Consumer 作为客户端去调用远程服务。每一个服务都可能会依赖几个下游服务,若某个服务 A 依赖的下游服务 B 出现了不稳定的情况,服务 A 请求 服务 B 的响应时间变长,从而服务 A 调用服务 B 的线程就会产生堆积,最终可能耗尽服务 A 的线程数。我们通过用并发线程数来控制对下游服务 B 的访问,来保证下游服务不可靠的时候,不会拖垮服务自身。基于这种场景,推荐给 Consumer 配置线程数模式的限流,来保证自身不被不稳定服务所影响。采用基于线程数的限流模式后,我们不需要再显式地去进行线程池隔离,Sentinel 会控制资源的线程数,超出的请求直接拒绝,直到堆积的线程处理完成,可以达到信号量隔离的效果。

    服务降级

    当服务依赖于多个下游服务,而某个下游服务调用非常慢时,会严重影响当前服务的调用。这里我们可以利用 Sentinel 熔断降级的功能,为调用端配置基于平均 RT 的降级规则。这样当调用链路中某个服务调用的平均 RT 升高,在一定的次数内超过配置的 RT 阈值,Sentinel 就会对此调用资源进行降级操作,接下来的调用都会立刻拒绝,直到过了一段设定的时间后才恢复,从而保护服务不被调用端短板所影响。同时可以配合 fallback 功能使用,在被降级的时候提供相应的处理逻辑。

    实战

    引入依赖

    1. com.alibaba.cloud
    2. spring-cloud-starter-alibaba-sentinel
    3. com.alibaba.csp
    4. sentinel-apache-dubbo-adapter

    yml中增加配置

    1. spring:
    2. cloud:
    3. sentinel:
    4. transport:
    5. # 添加sentinel的控制台地址
    6. dashboard: 127.0.0.1:8080
    7. #暴露actuator端点
    8. management:
    9. endpoints:
    10. web:
    11. exposure:
    12. include: '*'

    Consumer端配置流控规则

    1. @RequestMapping("/info/{id}")
    2. public User info(@PathVariable("id") Integer id) {
    3. User user = null;
    4. try {
    5. user = userService.getById(id);
    6. } catch (Exception e) {
    7. e.printStackTrace();
    8. }
    9. return user;
    10. }
    11. @PostConstruct
    12. public void init() {
    13. DubboAdapterGlobalConfig.setConsumerFallback(
    14. (invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult(
    15. new User(0,"===fallback=="), invocation));
    16. }

    测试: http://localhost:8080/user/info/1

    Provider端配置流控规则

    1. @RequestMapping("/getById/{id}")
    2. @SentinelResource("getById")
    3. public User getById(@PathVariable("id") Integer id) {
    4. User user = null;
    5. try {
    6. user = userMapper.getById(id);
    7. } catch (Exception e) {
    8. e.printStackTrace();
    9. }
    10. return user;
    11. }
    12. @PostConstruct
    13. public void init() {
    14. DubboAdapterGlobalConfig.setProviderFallback(
    15. (invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult(new User(0,"===provider fallback=="), invocation));
    16. }

    Consumer中配置mock实现,关闭provider服务,测试mock降级

    1. @DubboReference(mock = "com.tuling.mall.user.mock.UserServiceDubboMock")
    2. private UserService userService;
    3. public class UserServiceDubboMock implements UserService {
    4. @Override
    5. public List list() {
    6. return null;
    7. }
    8. @Override
    9. public User getById(Integer id) {
    10. return new User(0,"====mock===");
    11. }

    再次测试 : http://localhost:8080/user/info/1

  • 相关阅读:
    第二章 第十四节:字典的概念
    【JavaScript】cookie
    91. 存钱罐
    LeetCode每日一题(1807. Evaluate the Bracket Pairs of a String)
    Windows安装单节点Zookeeper
    C#界面里Control.ImeMode 属性的使用
    冯诺依曼体系结构、操作系统的认识
    【Java基础】Debug模式操作流程及案例:不死神兔、百钱百鸡
    Python+opencv绘制测试标版(棋盘格、纯色、十字叉心)
    吴峰光杀进 Linux 内核
  • 原文地址:https://blog.csdn.net/xq_adress/article/details/125884079