• 服务间的隔离及断路器-Hystrix



    服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心
    任务的正常运行。
    Hystrix主要是为了解决服务雪崩问题:

    1. 降级机制:当你的某一个服务出现超时时,资源不足,出现了异常,可以执行一个降级方法,返回一个托底数据
    2. 隔离:提供了一个Hystrix线程池,信号量,和tomcat的线程池相互隔离。
    3. 熔断:当你的某一个服务的失败率达到一定的阈值时,自动触发降级
    4. 缓存:请求缓存的功能
    1、降级机制实现

    导入依赖 customer

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4

    添加一个注解(启动类)

    @EnableCircuitBreaker
    
    • 1

    针对某一个接口去编写他的降级方法

    @GetMapping("/customer/{id}")
    @HystrixCommand(fallbackMethod = "findByIdFallBack")
    public Customer findById(@PathVariable Integer id){
        int i = 1/0;
        return searchClient.findById(id);
    }
    
    // findById的降级方法  方法的描述要和接口一致
    public Customer findByIdFallBack(Integer id){
        return new Customer(-1,"",0);
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在接口上添加注解

    @HystrixCommand(fallbackMethod = "findByIdFallBack")
    
    • 1

    2、线程隔离(线程池隔离,信号量

    如果使用Tomcat的线程池去接收用户的请求,使用当前线程去执行其他服务的功能,如果某一个服务出现了故障,导致tomcat的线程大量的堆积,导致Tomcat无法处理其他业务功能。

    • Hystrix的线程池(只要加上注解hystrixcommand默认),接收用户请求采用tomcat的线程池,执行业务代码,调用其他服务时,采用Hystrix的线程池。
    • 信号量,使用的还是Tomcat的线程池,帮助我们去管理Tomcat的线程池。

    Hystrix的线程池的配置

    配置信息namevalue
    线程隔离策略execution.isolation.strategyTHREAD ,SEMAPHORE
    指定超时时间execution.isolation.thread.timeoutInMilliseconds1000
    是否开启超时时间配置execution.timeout.enabledtrue
    超时之后是否中断线程execution.isolation.thread.interruptOnTimeouttrue
    取消任务后知否execution.isolation.thread.interruptOnCancelfalse

    代码实现

    @GetMapping("/customer/{id}")
    @HystrixCommand(fallbackMethod = "findByIdFallBack",commandProperties = {
            @HystrixProperty(name = "execution.isolation.strategy",value = "THREAD"),
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    public Customer findById(@PathVariable Integer id) throws InterruptedException {
        System.out.println(Thread.currentThread().getName());
        Thread.sleep(300);
        return searchClient.findById(id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    信号量的配置信息

    @GetMapping("/customer/{id}")
    @HystrixCommand(fallbackMethod = "findByIdFallBack",commandProperties = {
            @HystrixProperty(name = "execution.isolation.strategy",value = "SEMAPHORE")
    })
    public Customer findById(@PathVariable Integer id) throws InterruptedException {
        System.out.println(Thread.currentThread().getName());
        return searchClient.findById(id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3、断路器

    3.1 断路器介绍

    马丁福勒断路器论文:https://martinfowler.com/bliki/CircuitBreaker.html
    在调用指定服务时,如果说这个服务的失败率达到你输入的一个阈值,将断路器从closed状态,转变为open状态,指定服务时无法被访问的,如果你访问就直接走fallback方法,在一定的时间内,open状态会再次转变为half open状态,允许一个请求发送到我的指定服务,如果成功,转变为closed,如果失败,服务再次转变为open状态,会再次循环到half open,直到断路器回到一个closed状态。

    3.2 配置断路器的监控界面

    导入依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4

    在启动类中添加注解

    @EnableHystrixDashboard
    
    • 1

    配置一个Servlet路径,指定上Hystrix的Servlet

    @WebServlet("/hystrix.stream")
    public class HystrixServlet extends HystrixMetricsStreamServlet {
    }
    
    //------------------------------------------------------------
    // 在启动类上,添加扫描Servlet的注解
    @ServletComponentScan("com.qf.servlet")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    添加yml文件配置

    hystrix:
      dashboard:
        proxy-stream-allow-list: "localhost"
    
    • 1
    • 2
    • 3

    测试直接访问http://host:port/hystrix

    在当前位置输入映射好的servlet路径

    3.3 配置断路器的属性

    断路器的属性(默认10s秒中之内请求数)

    配置信息namevalue
    断路器的开关circuitBreaker.enabledtrue
    失败阈值的总请求数circuitBreaker.requestVolumeThreshold20
    请求总数失败率达到%多少时circuitBreaker.errorThresholdPercentage50
    断路器open状态后,多少秒是拒绝请求的circuitBreaker.sleepWindowInMilliseconds5000
    强制让服务拒绝请求circuitBreaker.forceOpenfalse
    强制让服务接收请求circuitBreaker.forceClosedfalse

    具体配置方式

    @GetMapping("/customer/{id}")
    @HystrixCommand(fallbackMethod = "findByIdFallBack",commandProperties = {
        @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "70"),
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "5000")
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4 请求缓存

    4.1 请求缓存介绍 相当于我们的学习的mybatis session 缓存
    • 请求缓存的声明周期是一次请求
    • 请求缓存是缓存当前线程中的一个方法,将方法参数作为key,方法的返回结果作为value
    • 在一次请求中,目标方法被调用过一次,以后就都会被缓存。


    4.2 请求缓存的实现

    创建一个Service,在Service中调用Search服务。

    @Service
    public class CustomerService {
    
        @Autowired
        private SearchClient searchClient;
    
    
        @CacheResult
        @HystrixCommand(commandKey = "findById")
        public Customer findById(@CacheKey Integer id) throws InterruptedException {
            return searchClient.findById(id);
        }
    
        @CacheRemove(commandKey = "findById")
        @HystrixCommand
        public void clearFindById(@CacheKey Integer id){
            System.out.println("findById被清空");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    使用请求缓存的注解
    @CacheResult:帮助我们缓存当前方法的返回结果(必须@HystrixCommand配合使用)
    @CacheRemove:帮助我们清楚某一个缓存信息(基于commandKey)
    @CacheKey:指定哪个方法参数作为缓存的标识

    编写Filter,去构建HystrixRequestContext

    @WebFilter("/*")
    public class HystrixRequestContextInitFilter implements Filter {
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HystrixRequestContext.initializeContext();
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    修改Controller

    public Customer findById(@PathVariable Integer id) throws InterruptedException {
        System.out.println(customerService.findById(id));
        System.out.println(customerService.findById(id));
        customerService.clearFindById(id);
        System.out.println(customerService.findById(id));
        System.out.println(customerService.findById(id));
        return searchClient.findById(id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    【Python】-----基础知识
    QT 使用百度语音识别--生成文本
    AI伦理专家:引领人工智能时代的道德导航者
    restful定义
    [附源码]计算机毕业设计基于SpringBoot文曦家教预约系统
    U盘分配单元大小建议设置多少?
    临时记录一下
    Android Studio Gradle中没有Task任务,没有Assemble任务,不能方便导出aar包
    EF core 如何撤销对对象的更改
    Linux文件描述符和打开文件之间的关系
  • 原文地址:https://blog.csdn.net/yc_Cabbage/article/details/126394997