傳統項目利用Hystrix實現熱點接口的服務隔離

 這段時間接了個需求,須要在我目前負責的數據系統上加個接口,主要是實現用戶行爲的記錄。前端對接的項目主要有公司的PC,WAP,WEIXIN,APP等,每一個端大概有兩臺左右的負載。由於目前個人這個項目主要是面向內部,負責數據運營相關的內容,是個單體項目。若是線上各個接入點不作限制,瞬間大量的併發進入必然會致使目前項目的崩潰,其餘的功能也沒法正常使用。前端

一、需求分析

經過前期的需求分析,目前線上系統沒法進行限流處理,因此最終解決問題仍是要從接口入手。java

目前我對接口的處理有兩種實現方案:git

  1. 能夠利用MQ實現消息的錯峯,將消息發送到MQ服務器。
  2. 實現對接口的隔離限流,避免當前接口對其餘功能的影響。

其實我認爲最好的實現方案就是第一種了,能夠保證消息的準確送達,避免併發資源的佔用。不過,由於公司條件的限制暫時不能新增中間件,因此只能在現有系統上進行改造,最後只能採用第二種方法了。github

二、Hystrix的簡單介紹

官方的定義就不說了,這裏簡單說下個人理解。Hystrix做爲斷路器主要是實現對服務的容錯保護,簡單來講就是服務隔離、服務降級、服務熔斷,服務限流這幾項。web

舉個常見的例子,當你某寶【搶購】一個產品時,常常會彈出[網絡錯誤,請重試。]的提示,這種時候是真的網絡問題嗎?顯示不是。這種狀況下實際上是對調用的接口進行了降級處理,當降級的次數或比例達到必定的條件後,斷路器就會直接打開,以後的訪問就會直接降級,而不會判斷是否降級了。達到對服務的容錯保護以及給用戶友好提示的目的。詳細的流程能夠看下圖。apache

通常Hystrix的容錯保護在微服務中是用在客戶端,也就是調用方。而我此次其實是用在了提供方,主要是前臺的項目我沒法控制,只能在接口上想方法了。目前我使用Hystrix的主要目的就是實現對服務的隔離和限流,而對降級和熔斷反而不是特別的關心,固然實際的使用要結合場景。json

由於通常Tomcat默認是一個線程池150個線程,若是單個熱點接口的請求過多,就會形成其餘功能沒有線程可用甚至直接程序崩潰的問題。Hystrix的服務隔離主要有兩種,經常使用的就是線程池隔離的方式,對熱點接口創建單獨的線程池避免對主程序的影響。另外一種是信號量的方式,用的場景不是太多。二者的區別其實就是一個增大系統的開銷,一個則直接限制了線程總的併發數,開銷更小一些。服務器

Hystrix服務調用邏輯圖網絡

三、項目中的應用實現

 本文是在傳統Spring項目中的應用,Springboot中的相關配置和依賴有稍許的不一樣。併發

maven依賴:

     <!-- hystrix -->
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-core</artifactId>
            <version>1.5.9</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-metrics-event-stream</artifactId>
            <version>1.5.9</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-javanica</artifactId>
            <version>1.5.9</version>
        </dependency>

 在Spring的配置文件中配置Hystrix的切面信息

    <bean id="hystrixAspect" class="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"></bean>
    <aop:aspectj-autoproxy />

主要是開啓註解的AOP掃描,這裏咱們能夠在這個類的源碼中看到實現

 能夠看到咱們主要是經過這個類切面掃描Hystrix的相關注解,以達到接口處理前,提早執行Hystrix相關邏輯的代碼。

/**
 * 提供客戶行爲接口
 *
 */
@Controller
@RequestMapping(value = "/test")
public class BehaviorController {
    Logger                                logger    = Logger.getLogger(BehaviorController.class);
    @Autowired
    private BehaviorService behaviorService;

    @RequestMapping(value="/addBehavior",method = RequestMethod.POST,produces = "application/json;charset=UTF-8")
    @ResponseBody
    @HystrixCommand(fallbackMethod = "fallback", threadPoolProperties = {  
            @HystrixProperty(name = "coreSize", value = "20"), @HystrixProperty(name = "maxQueueSize", value = "100"),
            @HystrixProperty(name = "queueSizeRejectionThreshold", value = "20")},
            commandProperties = {  
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "30000"),  
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20")
  
    })
    public String addBehavior(@RequestBody String parms) {

            //業務邏輯實現
            return result;
    }

    public String fallback(@RequestBody String parms){
        logger.info("fallback");
        //失敗的實現
        return result;
    }
}    

注意:
請求的接口必須爲public,fallback爲降級的接口邏輯,能夠爲private,也能夠爲public。

可是要特別注意fallback方法的返回值和參數必須和請求方法相同

另外須要說的是,當請求失敗、被拒絕、超時或者斷路器打開時,都會進入回退方法,可是進入回退方法並不意味着斷路器已經被打開。

四、經常使用參數的介紹

參數

描述

默認值

execution.isolation.strategy

隔離策略,有THREAD和SEMAPHORE

THREAD - 它在單獨的線程上執行,併發請求受線程池中的線程數量的限制
SEMAPHORE - 它在調用線程上執行,併發請求受到信號量計數的限制

默認使用THREAD模式,如下幾種場景可使用SEMAPHORE模式:

只想控制併發度

外部的方法已經作了線程隔離

調用的是本地方法或者可靠度很是高、耗時特別小的方法(如medis)

 

execution.isolation.thread.timeoutInMilliseconds

超時時間

默認值:1000

在THREAD模式下,達到超時時間,能夠中斷

在SEMAPHORE模式下,會等待執行完成後,再去判斷是否超時

設置標準:

有retry,99meantime+avg meantime

沒有retry,99.5meantime

 

execution.timeout.enabled

HystrixCommand.run()執行是否應該有超時。

默認值:true

fallback.isolation.semaphore.maxConcurrentRequests

設置在使用時容許執行fallback方法的最大併發請求數

默認值:10

circuitBreaker.requestVolumeThreshold

設置滾動時間窗中,斷路器熔斷的最小請求數

 默認值:20

滾動窗口默認10s,即10s內失敗請求達到20個,熔斷器即打開

 coreSize

設置執行命令線程池的核心線程數。

 默認值:10

maxQueueSize

設置執行命令線程池的核心線程數。

  默認值:-1

當設置爲-1時,線程池使用SynchronousQueue實現的隊列,不然將使用LinkedBlockingQueue實現的隊列

queueSizeRejectionThreshold

爲隊列設置拒絕閾值

默認值:5

當設置該參數後,即便隊列沒有達到最大值也能拒絕請求。

注意:當maxQueueSize屬性爲-1的時候,該屬性不會生效

另外須要特別注意的是:fallback的屬性maxConcurrentRequests,當請求達到了最大併發數時,後續的請求將會被拒絕並拋出異常(由於它已經沒有後續的fallback能夠被調用了),異常信息通常爲com.netflix.hystrix.exception.HystrixRuntimeException: xxxxxxx fallback execution rejected.

更多參數見官方文檔:https://github.com/Netflix/Hystrix/wiki/Configuration

另外附一個網友翻譯的文檔:https://blog.csdn.net/tongtong_use/article/details/78611225

五、接口測試

併發接口測試的方法不少,能夠寫代碼,也能夠用apache batch以及jmeter等工具。以經常使用的jmeter爲例,測試本接口。

設置環境變量:
JMETER_HOME   D:\apache-jmeter-3.0
CLASSPATH     %JMETER_HOME%\lib\ext\ApacheJMeter_core.jar;%JMETER_HOME%\lib\jorphan.jar;%JMETER_HOME%\lib/logkit-2.0.jar;

新建線程組:

設置併發參數:

第一個參數爲線程數,第二個參數爲啓動時間,第三個參數爲請求次數。以上述配置爲例即爲1秒內啓動50個線程,每一個線程請求一次。

添加HTTP請求

這裏設置請求的路徑,參數等等。

設置請求頭信息,因人而異

個人設置:Content-Type:application/json

表格查看結果

 

 查看結果:

 這個能夠根據機器的性能進行測試,以個人接口爲例,當設置併發數爲100之內時,基本上不會有降級處理,當併發數大於100時,就會有部分請求進入降級接口了。

六、接口監控

實際項目中,常常須要對咱們的接口和項目狀況進行監控,Hystrix已經爲咱們考慮到了。Hystrix提供了近乎實時的監控,Hystrix會實時的,累加的記錄全部關於HystrixCommand的執行信息,包括執行了每秒執行了多少請求,多少成功,多少失敗等等,更多指標請查看:https://github.com/Netflix/Hystrix/wiki/Metrics-and-Monitoring

在web.xml中添加下述配置:

    <!-- for Hystrix -->
    <servlet>
        <display-name>HystrixMetricsStreamServlet</display-name>
        <servlet-name>HystrixMetricsStreamServlet</servlet-name>
        <servlet-class>com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HystrixMetricsStreamServlet</servlet-name>
        <url-pattern>/hystrix.stream</url-pattern>
    </servlet-mapping>

啓動應用。訪問http://hostname:port/項目名/hystrix.stream,能夠看到下面信息

這種是最原生的監控使用方式,你們能夠另外集成Hystrix 提供的一個 Dashboard 應用。Dashboard 是一個單獨的應用,咱們能夠獨立部署。若是須要監控整個 Hystrix 集羣,就須要使用 Turbine 應用。Turbine 也是 Netflix 開源的一個服務。可是使用 Hystrix Stream 和 Turbine 存在一個明顯的不足,那就是沒法查看歷史的監控數據。解決這個問題就須要咱們本身來實現了。

監控的相關不是本文的重點,就很少介紹了,你們能夠百度下hystrix在微服務項目中監控的實現,這裏網上文章不少,基本上和傳統項目沒有任何區別了,你們能夠參考實現。

相關文章
相關標籤/搜索