Hystrix框架1--入門


介紹

在開發應用中或多或少會依賴各種外界的服務,利用各個服務來完成自己的業務需求,現在流行的微服務架構更是離不開各個服務之間的調用,這就導致整體應用的可用性依賴於各個依賴服務的可用性。
比如一個依賴30個可靠性為99.99%的服務的應用99.99^30 = 99.7%一下子就只能達到兩個9了。就算各個服務達到了可靠性,那總體來說每個月也有2個小時的不可用時間。更不用說會導致的連鎖反應。
這時我們就需要一個框架來隔離各個服務之間的調用,盡可能不影響業務的流程。
netflix開發了Hystrix這個框架就是為了這個隔離各個服務間調用而創建的框架。

hello world

首先來看一個簡單的Hello World例子
使用gradle導入hystrix的jar包

compile 'com.netflix.hystrix:hystrix-core:1.5.5'

之后就可以使用

//需要繼承HystrixCommand,還可以繼承HystrixObservableCommand只是對應接口、調用方法不同
public class CommandHelloWorld extends HystrixCommand<String> {

    private final String name;

    public CommandHelloWorld(String name) {
		//父類構造方法,只需要傳入一個GroupKey
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.name = name;
    }
	//真實的方法,在這調用服務等,並返回結果
    @Override
    protected String run()  {
		return "Hello " + name + "!";
    }
}

這樣就完成了一個Command。接下來調用這個Command

@Test
public void testSynchronous() {
    assertEquals("Hello World!", new CommandHelloWorld("World").execute());
    assertEquals("Hello Bob!", new CommandHelloWorld("Bob").execute());
}

這里直接新建一個實例並調用execute方法。就得到了想要的結果

調用方法

以上介紹了execute方法進行調用,這里execute是同步調用,會阻塞當前線程,Hystrix提供了許多異步的方法進行調用

//同步方法
@Test
public void testSynchronousSysOut() {
    System.out.println( new CommandHelloWorld("World").execute());
    System.out.println(  new CommandHelloWorld("Bob").execute());
}
//放入隊列獲得future異步調用
@Test
public void testAsynchronous2() throws Exception {

    Future<String> fWorld = new CommandHelloWorld("World").queue();
    Future<String> fBob = new CommandHelloWorld("Bob").queue();

    assertEquals("Hello World!", fWorld.get());
    assertEquals("Hello Bob!", fBob.get());
}

其實以上的方法原理都一樣,都是調用queue().get()方法,其中queue返回Future對象,之后對future阻塞進行取值。內部其實是調用toObservable().toBlocking().toFuture()來獲得future對象的
還有一種是使用RxJava的observable接口來進行調用的,Hystrix內部底層也是使用RxJava來實現的

//使用RxJava的Observable
@Test
public void testObservable() throws Exception {

    Observable<String> fWorld = new CommandHelloWorld("World").observe();
    Observable<String> fBob = new CommandHelloWorld("Bob").observe();

    // 阻塞
    assertEquals("Hello World!", fWorld.toBlocking().single());
    assertEquals("Hello Bob!", fBob.toBlocking().single());

    // 非阻塞 
    // - this is a verbose anonymous inner-class approach and doesn't do assertions
    fWorld.subscribe(new Observer<String>() {

        @Override
        public void onCompleted() {
            // nothing needed here
        }

        @Override
        public void onError(Throwable e) {
            e.printStackTrace();
        }

        @Override
        public void onNext(String v) {
            System.out.println("onNext: " + v);
        }

    });

fallback

以上只是簡單封裝了調用的接口,下面來看下Hystrix是如何應對調用的錯誤的
當在run方法中主動拋出異常,就會導致下面的錯誤信息

com.netflix.hystrix.exception.HystrixRuntimeException: CommandHelloWorld failed and no fallback available.

我們在Command中添加fallback方法

@Override
protected String run()  {
	throw RuntimeException("error");
	//return "Hello " + name + "!";
}
@Override
protected String getFallback() {
    return "Failure " + name + "!";
}

修改test方法

@Test
public void testSynchronous() {
    assertEquals("Failure World!", new CommandHelloWorld("World").execute());
    assertEquals("Failure Bob!", new CommandHelloWorld("Bob").execute());
}

這樣運行就沒有問題了,可以看到當run運行出錯時,將會調用fallback,返回值也由fallback提供,當然fallback也出錯那就沒有辦法了,所以需要盡量保證fallback不會出現異常。
其中值得注意的一點是當手動拋出HystrixBadRequestException時,Hystrix是不會調用fallback的。

總結

上面簡單介紹了Hystrix的使用,其中還有很多高級功能會在之后介紹


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM