Hystrix的簡單介紹

最近幾天我直在探索Netflix Hystrix library,領會到了這個優秀類庫提供的特性。

引用Hystrix網站的原話:
   Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, 
services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where 
failure is inevitable.
   Hystrix通過控制那些訪問遠程系統、服務和第三方庫的節點,從而對延遲和故障提供更強大的容錯能力,阻止故障的連鎖反應

,並允許你快速失敗並迅速恢復。

這裏有很多要分析的關鍵詞,然而體驗Hystrix的最佳方式就是親手做一個例子來試試。

一個不可預測的服務

考慮一個服務,一個攜帶json結構信息並且返回一個確認的奇怪服務。
{
    "id":"1",
    "payload": "Sample Payload",
    "throw_exception":false,
    "delay_by": 0
}

這個服務有一個payload屬性,但是額外多帶了兩個屬性。
delay_by 在延遲到達指定的毫秒數後返回一個確認響應。
throw_exceptions 在指定的延遲後導致異常

下面是響應例子:
{
 "id":"1",
 "received":"Sample Payload",
 "payload":"Reply Message"
}

這裏是我的github地址,可以下載示例代碼。在這個例子中我用到了Netflix Karyon2 ,示例代碼處理請求的部分非常簡潔。來看看
這個類庫用在這是多好用吧:

import com.netflix.governator.annotations.Configuration;
import rx.Observable;
import service1.domain.Message;
import service1.domain.MessageAcknowledgement;


import java.util.concurrent.TimeUnit;


public class MessageHandlerServiceImpl implements MessageHandlerService {


    @Configuration("reply.message")
    private String replyMessage;


    public Observable<MessageAcknowledgement> handleMessage(Message message) {
        logger.info("About to Acknowledge");
        return Observable.timer(message.getDelayBy(), TimeUnit.MILLISECONDS)
                .map(l -> message.isThrowException())
                .map(throwException -> {
                    if (throwException) {
                        throw new RuntimeException("Throwing an exception!");
                    }
                    return new MessageAcknowledgement(message.getId(), message.getPayload(), replyMessage);
                });
    }




}

在這裏,我們就有了一個可以響應隨意的延遲和失敗的候選服務了。

服務的客戶端

現在看一下客戶端,我們用Netflix Feign來進行調用,這是另一個很棒的類庫,需通過註解方式來使用:
package aggregate.service;


import aggregate.domain.Message;
import aggregate.domain.MessageAcknowledgement;
import feign.RequestLine;


public interface RemoteCallService {
    @RequestLine("POST /message")
    MessageAcknowledgement handleMessage(Message message);
}

在這幾行中,它創建了一個代理,其實現了使用配置的接口。

RmoteCallService remoteCallService = Feign.builder()
        .encoder(new JacksonEncoder())
        .decoder(new JacksonDecoder())
        .target(RemoteCallService.class, "http://127.0.0.1:8889");

我有多個針對這個遠程客戶端的委託調用,所有的都在下面這個url中
http://localhost:8888/noHystrix?message=Hello&delay_by=0&throw_exception=false
下面第一個例子是沒有使用Hystrix的例子。

沒有使用Hystrix的例子

在第一個例子中,考慮不用Hystrix來調用這個遠程服務,如果我嘗試以以下方式調用
http://localhost:8888/noHystrix?message=Hello&delay_by=5000&throw_exception=false或 
http://localhost:8888/noHystrix?message=Hello&delay_by=5000&throw_exception=true,
在這兩種實例中用戶對服務的請求都會在等待5秒後纔會收到響應。

有些事情在這裏就立即很明顯了:

1.如果服務響應緩慢,那麼客戶對服務的請求就會被強制等待到服務返回。

2.在高負載下,很有可能所有處理用戶請求的線程資源被耗竭,而不能響應用戶的進一步請求。

3.如果服務拋出異常,客戶端不能很好的處理。


Hystrix命令包裝遠程調用

在上一個例子中,我用50個用戶進行了一下壓力測試,得到結果如下:

================================================================================
---- Global Information --------------------------------------------------------
> request count                                         50 (OK=50     KO=0     )
> min response time                                   5007 (OK=5007   KO=-     )
> max response time                                  34088 (OK=34088  KO=-     )
> mean response time                                 17797 (OK=17797  KO=-     )
> std deviation                                       8760 (OK=8760   KO=-     )
> response time 50th percentile                      19532 (OK=19532  KO=-     )
> response time 75th percentile                      24386 (OK=24386  KO=-     )
> mean requests/sec                                  1.425 (OK=1.425  KO=-     )

基本上是5秒延遲,在到了75%的時候,延遲竟然達到了25秒。現在來看一下用Hystrix命令包裝後
調用的結果:

================================================================================
---- Global Information --------------------------------------------------------
> request count                                         50 (OK=50     KO=0     )
> min response time                                      1 (OK=1      KO=-     )
> max response time                                   1014 (OK=1014   KO=-     )
> mean response time                                    22 (OK=22     KO=-     )
> std deviation                                        141 (OK=141    KO=-     )
> response time 50th percentile                          2 (OK=2      KO=-     )
> response time 75th percentile                          2 (OK=2      KO=-     )
> mean requests/sec                                 48.123 (OK=48.123 KO=-     )

奇怪的是,測試到了75%的時候時間竟然是2毫秒!這怎麼可能呢!然而用了Hystrix提供的優秀工具後,
結果已經很明顯了。現在是本次測試的Hystrix控制檯視圖。

這裏的前10個請求已經超時,任何超過Hystrix默認時間1秒的,一但前10個交易失敗後,命令就會堵塞其他客戶對遠程服務的請求。
,因此會有較低的響應時間。爲什麼這些交易沒有顯示失敗呢,這是因爲這裏會有一個反饋,優雅的告訴用戶請求失敗了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章