zoukankan      html  css  js  c++  java
  • 【SpringCloud】Hystrix服务隔离(十二)

    服务隔离介绍

      当大多数人在使用Tomcat时,多个HTTP服务会共享一个线程池,假设其中一个HTTP服务访问的数据库响应非常慢,这将造成服务响应时间延迟增加,大多数线程阻塞等待数据响应返回,导致整个Tomcat线程池都被该服务占用,甚至拖垮整个Tomcat。因此,如果我们能把不同HTTP服务隔离到不同的线程池,则某个HTTP服务的线程池满了也不会对其他服务造成灾难性故障。这就需要线程隔离或者信号量隔离来实现了。

      使用线程隔离或信号隔离的目的是为不同的服务分配一定的资源,当自己的资源用完,直接返回失败而不是占用别人的资源。

      Hystrix实现服务隔离两种方案

      Hystrix的资源隔离策略有两种,分别为:线程池和信号量。

    线程池方式

      优点:

      1、 使用线程池隔离可以完全隔离第三方应用,请求线程可以快速放回。

      2、 请求线程可以继续接受新的请求,如果出现问题线程池隔离是独立的不会影响其他应用。

      3、 当失败的应用再次变得可用时,线程池将清理并可立即恢复,而不需要一个长时间的恢复。

      4、 独立的线程池提高了并发性

      缺点:

      线程池隔离的主要缺点是它们增加计算开销(CPU)。每个命令的执行涉及到排队、调度和上 下文切换都是在一个单独的线程上运行的。

      线程池方式案例

      1、使用上一章项目工程,在服务端项目的业务类Service中编写如下方法:

     1 // 服务限流
     2 @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_Thread",
     3         // 属性设置参考:HystrixCommandProperties
     4         commandProperties = {
     5                 // 隔离策略,有THREAD和SEMAPHORE
     6                 @HystrixProperty(name="execution.isolation.strategy", value="THREAD")
     7         },
     8         threadPoolProperties = {
     9                 // 线程池核心线程数
    10                 @HystrixProperty(name = "coreSize", value = "3"),
    11                 // 队列最大长度
    12                 @HystrixProperty(name = "maxQueueSize", value = "5"),
    13                 // 排队线程数量阈值,默认为5,达到时拒绝,如果配置了该选项,队列的大小是该队列
    14                 @HystrixProperty(name = "queueSizeRejectionThreshold", value = "7")
    15         })
    16 public String paymentCircuitBreakerThread(@PathVariable("id") Integer id){
    17     int second = 500;
    18     try {
    19         // 休眠500毫秒
    20         TimeUnit.MILLISECONDS.sleep(second);
    21     } catch (InterruptedException e) {
    22 //            e.printStackTrace();
    23     }
    24     // 异常
    25 //        int n = 10/0;
    26     String result = "线程池:" + Thread.currentThread().getName()
    27             + ",paymentCircuitBreakerThreadPool,ID == " + id
    28             + ",耗时" + second + "毫秒";
    29     return result;
    30 }
    31 
    32 public String paymentCircuitBreaker_Thread(@PathVariable("id") Integer id){
    33     return " paymentCircuitBreaker_Thread 服务限流,ID == " + id;
    34 }

      2、在controller中调用该方法

    1 // 线程
    2 @GetMapping(value = "/payment/hystrix/thread/{id}")
    3 public String paymentCircuitBreakerThreadPool(@PathVariable("id") Integer id) {
    4     String result = paymentService.paymentCircuitBreakerThread(id);
    5     log.info("result===" + result);
    6     return result;
    7 }

      3、重启项目,使用JMeter进行并发测试,测试url地址:http://localhost:8008/payment/hystrix/thread/1

        测试发现,有一部分请求调用了fallback方法,一部分正常响应

        

    信号量方式  

      使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,当请求进来时先判断计数 器的数值,若超过设置的最大线程个数则拒绝该请求,若不超过则通行,这时候计数器+1,请求返 回成功后计数器-1。

      与线程池隔离最大不同在于执行依赖代码的线程依然是请求线程

      提示:信号量的大小可以动态调整, 线程池大小不可以

      信号量方式案例

      1、使用上一章项目工程,在服务端项目的业务类Service中编写如下方法:

     1 // 服务限流
     2 @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_Semaphore",
     3         // 属性设置参考:HystrixCommandProperties
     4         commandProperties = {
     5                 // 隔离策略,有THREAD和SEMAPHORE
     6                 // THREAD - 它在单独的线程上执行,并发请求受线程池中的线程数量的限制(默认)
     7                 // SEMAPHORE - 它在调用线程上执行,并发请求受到信号量计数的限制
     8                 @HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE"),
     9                 // 设置在使用时允许到HystrixCommand.run()方法的最大请求数。默认值:10 ,SEMAPHORE模式有效
    10                 @HystrixProperty(name="execution.isolation.semaphore.maxConcurrentRequests", value="1")
    11 
    12         })
    13 public String paymentCircuitBreakerSemaphore(@PathVariable("id") Integer id){
    14     int second = 500;
    15     try {
    16         // 休眠500毫秒
    17         TimeUnit.MILLISECONDS.sleep(second);
    18     } catch (InterruptedException e) {
    19 //            e.printStackTrace();
    20     }
    21     // 异常
    22 //        int n = 10/0;
    23     String result = "线程池:" + Thread.currentThread().getName()
    24             + ",paymentCircuitBreaker_Semaphore,ID == " + id
    25             + ",耗时" + second + "毫秒";
    26     return result;
    27 }
    28 
    29 public String paymentCircuitBreaker_Semaphore(@PathVariable("id") Integer id){
    30     return " paymentCircuitBreaker_Semaphore 服务限流,ID == " + id;
    31 }

      2、在controller中调用该方法

    1 // 信号量
    2 @GetMapping(value = "/payment/hystrix/semaphore/{id}")
    3 public String paymentCircuitBreakerLimit(@PathVariable("id") Integer id) {
    4     String result = paymentService.paymentCircuitBreakerSemaphore(id);
    5     log.info("result===" + result);
    6     return result;
    7 }

      3、重启项目,使用JMeter进行并发测试,测试url地址:http://localhost:8008/payment/hystrix/semaphore/1

        测试发现,有一部分请求调用了fallback方法,一部分正常响应

        

  • 相关阅读:
    extjs 登录
    Digg 顶 踩(jQuery+Ajax)
    长度不能小于 0。 参数名: length
    .net 资料
    Micromedia Flash Player已终止一项可能不安全的操作解决办法
    SQL SERVER 与ACCESS、EXCEL的数据转换
    排名 sql
    FileUploaderAJAX 无刷新上传
    Microsoft Office Access ActiveX 部件不能创建对象
    流量分析作用
  • 原文地址:https://www.cnblogs.com/h--d/p/12716811.html
Copyright © 2011-2022 走看看