Hystrix常用功能介紹

Hystrix是一個簡單易用的熔斷中間件弹渔,本篇文章會介紹下常規(guī)的使用方式。

目錄

  • helloWorld初窺Hystrix
  • HystrixCommand基本配置端壳、同步和異步執(zhí)行
  • request cache的使用
  • fallback
    • default fallback
    • 單級fallback
    • 多級fallback
    • 主次多HystrixCommand fallback
  • 接入現(xiàn)有業(yè)務(wù)
  • 總結(jié)

helloWorld初窺Hystrix

先貼代碼

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;

public class CommandHelloWorld extends HystrixCommand<String> {

    private final String name;

    public CommandHelloWorld(String name) {
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.name = name;
    }

    @Override
    protected String run() {
        return "Hello " + name + "!";
    }
}

代碼很簡單,聲明一個類CommandHelloWorld竟纳,集成HystrixCommand, HystrixCommand攜帶泛型,泛型的類型就是我們的執(zhí)行方法run()返回的結(jié)果的類型疚鲤。邏輯執(zhí)行體就是run方法的實現(xiàn)。
構(gòu)造方法至少要傳遞一個分組相關(guān)的配置給父類才能實現(xiàn)實例化缘挑,具體用來干什么的后面會描述集歇。

下面測試一下

public class CommandHelloWorldTest {
    @Test
    public void test_01(){
        String result = new CommandHelloWorld("world").execute();
        Assert.assertEquals("Hello world!",result);
    }
}

就這樣第一個hellworld就跑起來,so easy

HystrixCommand基本配置语淘、同步和異步執(zhí)行

1.HystrixCommand诲宇、Group、ThreadPool 配置

Hystrix把執(zhí)行都包裝成一個HystrixCommand惶翻,并啟用線程池實現(xiàn)多個依賴執(zhí)行的隔離姑蓝。
上面的代碼集成了HystrixCommand并實現(xiàn)了類似分組key的構(gòu)造方法,那么分組是用來做什么呢吕粗?還有沒有其他類似的東西纺荧?怎么沒有看到線程配置呢?

Hystrix每個command都有對應(yīng)的commandKey可以認(rèn)為是command的名字颅筋,默認(rèn)是當(dāng)前類的名字getClass().getSimpleName(),每個command也都一個歸屬的分組宙暇,這兩個東西主要方便Hystrix進行監(jiān)控、報警等议泵。
HystrixCommand使用的線程池也有線程池key占贫,以及對應(yīng)線程相關(guān)的配置

下面是代碼的實現(xiàn)方式
自定義command key

HystrixCommandKey.Factory.asKey("HelloWorld")

自定義command group

HystrixCommandGroupKey.Factory.asKey("ExampleGroup")

那么線程池呢?

HystrixThreadPoolKey.Factory.asKey("HelloWorldPool")

Hystrix command配置有熔斷閥值先口,熔斷百分比等配置型奥,ThreadPoll有線程池大小瞳收,隊列大小等配置,如何設(shè)置厢汹?
Hystrix的配置可以通過Setter進行構(gòu)造

  public CommandHelloWorld(){
        super(Setter
                //分組key
                .withGroupKey(HystrixCommandGroupKey.Factory.asKey("helloWorldGroup"))

                //commandKey
                .andCommandKey(HystrixCommandKey.Factory.asKey("commandHelloWorld"))
                //command屬性配置
                .andCommandPropertiesDefaults(HystrixPropertiesCommandDefault.Setter().withCircuitBreakerEnabled(true).withCircuitBreakerForceOpen(true))

                //線程池key
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("helloWorld_Poll"))
                //線程池屬性配置
                .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(20).withMaxQueueSize(25))
        );
    }

其它的詳細配置可參考https://github.com/Netflix/Hystrix/wiki/Configuration 后續(xù)也會整理對應(yīng)的配置介紹文章螟深。

2.HystrixCommand和分組、線程池三者的關(guān)系

commandKey分組內(nèi)唯一坑匠,HystrixCommand和分組血崭、線程池是多對1的關(guān)系。分組和線程池沒關(guān)系厘灼。

3.HystrixCommand如何執(zhí)行夹纫?同步?異步设凹?

同步
從helloWorld的例子可以看到舰讹,我們實例化了我們的HelloWorldCommand,調(diào)用了execute方法,從而執(zhí)行了command的Run()闪朱。這種是同步的執(zhí)行方式月匣。

異步執(zhí)行
在實際業(yè)務(wù)中,有時候我們會同時觸發(fā)多個業(yè)務(wù)依賴的調(diào)用奋姿,而這些業(yè)務(wù)又相互不依賴這時候很適合并行執(zhí)行锄开,我們可以使用Future方式,調(diào)用command的queue()方法称诗。
我們可以再寫一個helloWorld2

public class CommandHelloWorld2 extends HystrixCommand<String> {

    private final String name;

    public CommandHelloWorld2(String name) {
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.name = name;
    }

    @Override
    protected String run() {
        return "Hello " + name + "!";
    }
}

具體異步調(diào)用

    @Test
    public void test_02() throws ExecutionException, InterruptedException {
        Future<String> future1 = new CommandHelloWorld("world").queue();
        Future<String> future2 = new CommandHelloWorld2("world").queue();

        Assert.assertEquals("Hello world!",future1.get());
        Assert.assertEquals("Hello world!",future2.get());
    }

request cache的使用

先貼代碼

public class CachedCommand extends HystrixCommand<String> {

    private String key;

    private static final HystrixCommandKey COMMANDKEY = HystrixCommandKey.Factory.asKey("CachedCommand_cmd");

    protected CachedCommand(String key){
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("CachedCommand"))
                .andCommandKey(COMMANDKEY));
        this.key = key;
    }

    @Override
    protected String getCacheKey() {
        return this.key;
    }

    public static void flushCache(String key) {
        HystrixRequestCache.getInstance(COMMANDKEY,
                HystrixConcurrencyStrategyDefault.getInstance()).clear(key);
    }

    @Override
    protected String run() throws Exception {
        return "hello "+ key +" !";
    }
}

Hystrix的cache萍悴,個人的理解就是在上下文中,多次請求同一個command寓免,返回值不會發(fā)生改變的時候可以使用癣诱。cache如果要生效,必須聲明上下文

HystrixRequestContext context = HystrixRequestContext.initializeContext();

....... command 的調(diào)用 ........

context.shutdown();

清緩存袜香,就是先獲得到command然后把對應(yīng)的key刪除

 HystrixRequestCache.getInstance(COMMANDKEY,
                HystrixConcurrencyStrategyDefault.getInstance()).clear(key);

接下來看下完整的調(diào)用

    @Test
    public void test_no_cache(){
        HystrixRequestContext context = HystrixRequestContext.initializeContext();

        String hahahah = "hahahah";
        CachedCommand cachedCommand = new CachedCommand(hahahah);
        Assert.assertEquals("hello hahahah !", cachedCommand.execute());
        Assert.assertFalse(cachedCommand.isResponseFromCache());

        CachedCommand cachedCommand2 = new CachedCommand(hahahah);
        Assert.assertEquals("hello hahahah !", cachedCommand2.execute());
        Assert.assertTrue(cachedCommand2.isResponseFromCache());


        //清除緩存
        CachedCommand.flushCache(hahahah);

        CachedCommand cachedCommand3 = new CachedCommand(hahahah);
        Assert.assertEquals("hello hahahah !", cachedCommand3.execute());
        Assert.assertFalse(cachedCommand3.isResponseFromCache());

        context.shutdown();
    }

fallback

1.單個fallback

fallback就是當(dāng)HystrixCommand 執(zhí)行失敗的時候走的后備邏輯撕予,只要實現(xiàn)HystrixCommand 的fallback方法即可

public class CommandWithFallBack extends HystrixCommand<String> {

    private final boolean throwException;

    public CommandWithFallBack(boolean throwException) {
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.throwException = throwException;
    }

    @Override
    protected String run() {
        if (throwException) {
            throw new RuntimeException("failure from CommandThatFailsFast");
        } else {
            return "success";
        }
    }

    @Override
    protected String getFallback() {
        return "I'm fallback";
    }


}

測試結(jié)果

    @Test
    public void testSuccess() {
        assertEquals("success", new CommandWithFallBack(false).execute());
    }

    @Test
    public void testFailure() {
        try {
            assertEquals("I'm fallback", new CommandWithFallBack(true).execute());
        } catch (HystrixRuntimeException e) {
            Assert.fail();
        }
    }
2.多級fallback

當(dāng)我們執(zhí)行業(yè)務(wù)的時候,有時候會有備用方案1蜈首、備用方案2实抡,當(dāng)備用方案1失敗的時候啟用備用方案2,所以可以使用多級fallback疾就。
多級fallback沒有名字那么神秘澜术,說到底其實就是HystrixCommand1執(zhí)行fallback1, fallback1的執(zhí)行嵌入HystrixCommand2,當(dāng)HystrixCommand2執(zhí)行失敗的時候猬腰,觸發(fā)HystrixCommand2的fallback2鸟废,以此循環(huán)下去實現(xiàn)多級fallback,暫未上限姑荷,只要你的方法棧撐的起盒延。

代碼實現(xiàn)

command1

public class CommandWithMultiFallBack1 extends HystrixCommand<String> {

    private final boolean throwException;

    public CommandWithMultiFallBack1(boolean throwException) {
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.throwException = throwException;
    }

    @Override
    protected String run() {
        if (throwException) {
            throw new RuntimeException("failure from CommandThatFailsFast");
        } else {
            return "success";
        }
    }

    @Override
    protected String getFallback() {
        return new CommandWithMultiFallBack2(true).execute();
    }


}

command2

public class CommandWithMultiFallBack2 extends HystrixCommand<String> {

    private final boolean throwException;

    public CommandWithMultiFallBack2(boolean throwException) {
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.throwException = throwException;
    }

    @Override
    protected String run() {
        if (throwException) {
            throw new RuntimeException("failure from CommandThatFailsFast");
        } else {
            return "I'm fallback1";
        }
    }

    @Override
    protected String getFallback() {
        return "I'm fallback2";
    }

調(diào)用測試

    @Test
    public void testMultiFailure(){
        try {
            assertEquals("I'm fallback2", new CommandWithMultiFallBack1(true).execute());
        } catch (HystrixRuntimeException e) {
            Assert.fail();
        }
    }
3.主次多HystrixCommand fallback

這里探討的是 主Command里串行執(zhí)行 多個Command時的fallback執(zhí)行邏輯

這里就不貼代碼了缩擂,fallback的跳轉(zhuǎn)也比較好理解,次command添寺,不管任何一個執(zhí)行失敗都認(rèn)為主command的run執(zhí)行失敗胯盯,進而進入主command的fallback

接入現(xiàn)有業(yè)務(wù)

上面的章節(jié)主要在解釋如何使用HystrixCommand,但是我們在開發(fā)中都已經(jīng)分好了各種業(yè)務(wù)的servie,如何套入這個Hystrix?

1.模擬業(yè)務(wù)場景

假設(shè)我們要加載商品詳情頁计露,需要加載商品信息博脑、用戶信息、店鋪信息
接入Hystrix前的代碼(代碼有點天真票罐,只是為了表述下意思)

//主功能類
public class GoodsService {

    private UserService userService = new UserService();
    private ShopService shopService = new ShopService();

    /**
     * 獲取商品詳情
     * @return
     */
    public GoodsDetailFrontModel getGoodsFrontDetail(){
        GoodsDetailFrontModel goodsDetailFrontModel = new GoodsDetailFrontModel();
        goodsDetailFrontModel.setTitle("這是一個測試商品");
        goodsDetailFrontModel.setPrice(10000L);

        UserModel userInfo = userService.getUserInfo(1000001L);
        ShopModel shopInfo = shopService.getShopInfo(2001L);

        goodsDetailFrontModel.setShopModel(shopInfo);
        goodsDetailFrontModel.setUserModel(userInfo);

        return goodsDetailFrontModel;
    }

}

//依賴的用戶類
public class UserService {

    /**
     * 獲取用戶信息
     * @param userId
     * @return
     */
    public UserModel getUserInfo(Long userId){
        return new UserModel();
    }
}

下面我們對用戶服務(wù)套入Hystrix叉趣,為了不侵入我們依賴的服務(wù),我們新建一個門戶類该押,包裝Hystrix相關(guān)的代碼

public class UserServiceFacade extends HystrixCommand<UserModel> {

    //原業(yè)務(wù)service
    private UserService userService = new UserService();

    private Long userId;

    protected UserServiceFacade() {
        super(HystrixCommandGroupKey.Factory.asKey("UserServiceFacade"));
    }

    @Override
    protected UserModel run() throws Exception {
        return userService.getUserInfo(userId);
    }


    /**
      *如果執(zhí)行失敗則返回游客身份
     **/
    @Override
    protected UserModel getFallback() {
        UserModel userModel = new UserModel();
        userModel.setName("游客");
        return userModel;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }
}

然后我們再看下主執(zhí)行類

GoodsService

   /**
     * 獲取商品詳情
     * @return
     */
    public GoodsDetailFrontModel getGoodsFrontDetail(){
        GoodsDetailFrontModel goodsDetailFrontModel = new GoodsDetailFrontModel();
        goodsDetailFrontModel.setTitle("這是一個測試商品");
        goodsDetailFrontModel.setPrice(10000L);

        //原寫法
        //UserModel userInfo = userService.getUserInfo(1000001L);

        //這里替換成了調(diào)用用戶門面類
        UserServiceFacade userServiceFacade = new UserServiceFacade();
        userServiceFacade.setUserId(1000001L);
        UserModel userInfo = userServiceFacade.execute();


        ShopModel shopInfo = shopService.getShopInfo(2001L);

        goodsDetailFrontModel.setShopModel(shopInfo);
        goodsDetailFrontModel.setUserModel(userInfo);

        return goodsDetailFrontModel;
    }

上面的代碼提供一個套入的思路疗杉,官方原生的Hystrix就是這樣接入的,這里注意一點蚕礼,HystrixCommand每次執(zhí)行都需要new一個烟具,不能使用單例,一個command實例只能執(zhí)行一次,上面的代碼也就是我們的userServiceFacade奠蹬,每次執(zhí)行都需要new一個新的對象朝聋。

總結(jié)

上面介紹了Hystrix的常規(guī)用法,也是我們公司目前的使用方式囤躁,官網(wǎng)還有HystrixObservableCommand的使用方式介紹玖翅,主要是rxjava的使用方式,獲取到observable可以進行更加靈活的處理割以,這里就不介紹了。

回顧下应媚,Hystrix能給我們帶來什么好處
1.多業(yè)務(wù)依賴隔離严沥,不會相互影響,并可以根據(jù)需要給不同的依賴分不同的線程資源
2.業(yè)務(wù)依賴fail-fast
3.依賴服務(wù)恢復(fù)中姜,能合理感知并恢復(fù)對服務(wù)的依賴
4.對依賴服務(wù)限流消玄,Hystrix對每個業(yè)務(wù)的依賴都包裝成了一個command,并分配線程池,線程池的容量也就是能下發(fā)請求的能力丢胚,防止雪崩

使用的介紹先到這里了翩瓜,后續(xù)大家有什么建議或者想法可以一起交流、碰撞携龟。

系列文章推薦
Hystrix熔斷框架介紹
Hystrix常用功能介紹
Hystrix執(zhí)行原理
Hystrix熔斷器執(zhí)行機制
Hystrix超時實現(xiàn)機制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末兔跌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子峡蟋,更是在濱河造成了極大的恐慌坟桅,老刑警劉巖华望,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異仅乓,居然都是意外死亡赖舟,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門夸楣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宾抓,“玉大人,你說我怎么就攤上這事豫喧∈矗” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵嘿棘,是天一觀的道長劲腿。 經(jīng)常有香客問我,道長鸟妙,這世上最難降的妖魔是什么焦人? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮重父,結(jié)果婚禮上花椭,老公的妹妹穿的比我還像新娘。我一直安慰自己房午,他們只是感情好矿辽,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著郭厌,像睡著了一般袋倔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上折柠,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天宾娜,我揣著相機與錄音,去河邊找鬼扇售。 笑死前塔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的承冰。 我是一名探鬼主播华弓,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼困乒!你這毒婦竟也來了寂屏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎凑保,沒想到半個月后冈爹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡欧引,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年频伤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芝此。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡憋肖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出婚苹,到底是詐尸還是另有隱情岸更,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布膊升,位于F島的核電站怎炊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏廓译。R本人自食惡果不足惜评肆,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望非区。 院中可真熱鬧瓜挽,春花似錦、人聲如沸征绸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽管怠。三九已至淆衷,卻和暖如春故硅,著一層夾襖步出監(jiān)牢的瞬間蛉谜,已是汗流浹背血公。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工线椰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人朴肺。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辕宏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理砾莱,服務(wù)發(fā)現(xiàn)瑞筐,斷路器,智...
    卡卡羅2017閱讀 134,656評論 18 139
  • 原文:https://my.oschina.net/7001/blog/1619842 摘要: Hystrix是N...
    laosijikaichele閱讀 4,311評論 0 25
  • 一腊瑟、認(rèn)識Hystrix Hystrix是Netflix開源的一款容錯框架聚假,包含常用的容錯方法:線程池隔離块蚌、信號量隔...
    新棟BOOK閱讀 4,045評論 0 19
  • 一、認(rèn)識Hystrix Hystrix是Netflix開源的一款容錯框架膘格,包含常用的容錯方法:線程池隔離峭范、信號量隔...
    新棟BOOK閱讀 26,474評論 1 37
  • 我的男朋友太可愛了!1窦I纯亍!2饲亍L鸷Α! 特別粘人球昨。 我說我尔店。
    c0d843f4cb28閱讀 156評論 0 1