Hystrix 使用指南(1):基本使用

一、前言

現(xiàn)在分布式系統(tǒng)的規(guī)模不斷增加漠魏,對可用性的要求也越來越高倔矾。在各種高可用設計模式中,熔斷柱锹、隔離哪自、降級是經(jīng)常被使用的。而相關的技術禁熏,如 Hystrix壤巷,便成為最近的熱點。

從16年初開始瞧毙,我所在的團隊便開始應用 Hystrix胧华。為了進一步推動系統(tǒng)可用性升級寄症,普及 Hystrix 在團隊內(nèi)的使用,我便有了寫一系列 Hystrix 相關的文章的想法矩动。

雖然 Hystrix 有著很詳細的官方文檔有巧,但出于語言和更多細節(jié)介紹、實踐建議的考慮悲没,還是需要一些文章作為補充篮迎。

二、什么是 Hystrix

雖然 Hystrix 已算不上什么新技術示姿,但還是要簡單介紹一下柑潦。

Hystrix 是一個在調(diào)用端上,實現(xiàn)斷路器模式峻凫,以及隔艙模式渗鬼,通過避免級聯(lián)故障,提高系統(tǒng)容錯能力荧琼,從而實現(xiàn)高可用設計的一個 Java 類庫譬胎。

上面這段介紹是我的一個簡要總結。更具體的介紹可以參照官網(wǎng)命锄。

三堰乔、Hystrix 的基本使用

Hystrix 的主要目的是保護跨進程調(diào)用,避免因為超時等問題脐恩,導致的級聯(lián)故障镐侯。Hystrix 的實現(xiàn)方法是封裝跨進程調(diào)用。具體的使用方式有多種:從編程方式看可分為編程方式和注解方式兩種驶冒;從調(diào)用方式看可分為同步調(diào)用方式苟翻、異步調(diào)用方式和反應式調(diào)用方式三種。

我們先來看最常見的同步編程方式:

代碼示例

@Component
public class AuthService {
  @Autowired
  private UserService userService;

  public boolean validateUser(String userId) {
    User user = new GetUserCommand(userId).execute(); // 6
    if (user == null) {
      return false;
    } else {
      return user.isValid();
    }
  }

  class GetUserCommand extends HystrixCommand<User> { // 1
    private Long userId;

    public GetUserCommand(Long userId) { // 2
      super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("UserService")) // 3
          .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
              .withCoreSize(20) // 3
          )
          .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
              .withExecutionTimeoutInMilliseconds(100) // 3
          )
      );
      this.userId = userId;
    }

    @Override
    public User run() throws Exception {
      return userService.getUserById(userId); // 4
    }

    @Override
    public User getFallback() {
      return new InvalidUser(); // 5
    }
  }
}

代碼解釋

  1. Hystrix 常見的使用方法是在一個業(yè)務處理類(在本例中是 AuthService)新建一個內(nèi)部類(本例中是 GetUserCommand)骗污。這個內(nèi)部類需要擴展 HystrixCommand崇猫。之所以使用內(nèi)部類是因為 Hystrix 通常用來封裝一次遠程調(diào)用,一般是直接調(diào)用一個業(yè)務方法需忿。這個業(yè)務方法通常位于一個業(yè)務處理類或這個業(yè)務處理類所依賴的類中诅炉。所以使用內(nèi)部類的方式可以簡化這種調(diào)用。擴展 HystrixCommand 還需聲明一個泛型類型屋厘,這個泛型類型表示這個 HystrixCommand 的返回值涕烧。
  2. 定義一個 HystrixCommand 還需定義一個構造函數(shù)。這個構造函數(shù)十分重要汗洒,因為在使用這個 HystrixCommand 時议纯,需要通過構造函數(shù)傳遞參數(shù)。
  3. 在構造函數(shù)中仲翎,需要調(diào)用父構造函數(shù)對當前的 HystrixCommand 進行配置痹扇。主要的配置主要有三個:GroupKey、ThreadPoolSize 和 Timeout溯香。具體的配置方式有多種鲫构,較常用的一種方式是通過一個名為 Setter 的 Builder 類進行配置。
    1. GroupKey 通過 Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("UserService")) 語句進行配置玫坛;
    2. ThreadPoolSize 通過 .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(20)) 語句進行配置结笨;
    3. Timeout 通過 .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(100) 語句進行配置;
  4. 通過實現(xiàn) run() 方法湿镀,在其中實現(xiàn)業(yè)務邏輯炕吸。通常是調(diào)用外部類的方法或外部類依賴的方法。
  5. 通過實現(xiàn) getFallback() 方法勉痴,實現(xiàn)失敗邏輯赫模,可以在其中實現(xiàn)降級等功能。
  6. 編寫完 GetUserCommand 之后蒸矛,使用的時候每次都需要 new 一個新對象瀑罗,再調(diào)用 execute() 方法。注意雏掠,不要調(diào)用 run() 方法斩祭,否則熔斷、隔離等功能是不生效的乡话。

四摧玫、Hystrix 的基本配置

上面的部分介紹了 HystrixCommand 的基本使用方法,但只是簡單介紹了幾個配置绑青。所以诬像,下面將對 HystrixCommand 的相關配置的作用做一個較為詳細的介紹。

配置模式

Hystrix 的配置有三個維度:全局默認配置闸婴、Instance 默認配置颅停、Instance 動態(tài)配置。除了少部分配置項外掠拳,大部分配置都支持動態(tài)修改癞揉。接下來介紹一下一些主要參數(shù)的 Instance 默認配置方式。這種配置方式也是使用 Hystrix 最先接觸到的配置方式溺欧。

Command Group

GroupKey 是 HystrixCommand 不可缺少的配置喊熟,其它配置均為可選。所以姐刁,使用 Hystrix 可以使用下面的代碼:

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 + "!";
  }
}

HystrixCommandGroupKey 是一個接口芥牌,所以除了可以使用 HystrixCommandGroupKey.Factory.asKey("ExampleGroup") 的方式定義以外,也可以直接實現(xiàn)這個接口聂使。比如使用如下的方式:

public enum Groups implements HystrixCommandGroupKey {
  GROUP_1
}

class EnumGroupCommand extends HystrixCommand<String> {
  EnumGroupCommand() {
    super(Groups.GROUP_1);
  }

  @Override
  protected String run() throws Exception {
    LOGGER.info("Thread of Command: {}", Thread.currentThread().getName());
    return null;
  }
}

如上面代碼這樣壁拉,使用自定義的枚舉類谬俄,實現(xiàn) HystrixCommandGroupKey 接口,可以統(tǒng)一 Hystrix Command Group 的定義弃理,簡化配置溃论。

HystrixCommandGroupKey 的作用主要有兩個:

  1. 一是起到分組監(jiān)控、報警的作用痘昌。后面的文章會對監(jiān)控等方面進行介紹钥勋;
  2. 二是在不配置 HystrixThreadPoolKey 的情況下,起到分組線程池的作用辆苔。即默認使用 HystrixCommandGroupKey 去命名線程池算灸。使用同一個 HystrixCommandGroupKey 且沒有自定義 HystrixThreadPoolKeyHystrixCommand 將使用同一個線程池。

Command Thread-Pool

雖然 HystrixCommandGroupKey 可以起到隔離線程池的作用驻啤,但是無法起到對線程池進行精細配置的作用菲驴。所以這里就需要線程池進行配置:

Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("MyService"))
    .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("MyThreadPool"))
    .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
        .withCoreSize(10)
        .withKeepAliveTimeMinutes(1)
        .withMaxQueueSize(-1)
    )
)

andThreadPoolPropertiesDefaults 配置中的數(shù)值表示的是默認值。接下來逐項介紹:

  1. andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("MyThreadPool")) 這是配置 ThreadPoolKey骑冗。如果需要在同一個 GroupKey 下面配置不同的 ThreadPool 就需要這個配置谢翎。
  2. withCoreSize(10) 用來配置線程池大小。Hystrix 對線程池的配置有一些限制沐旨,這里只能配置線程數(shù)的 Core Size森逮,不能配置 Max Size。不配置的話使用的默認值是 10磁携。
  3. withKeepAliveTimeMinutes(1) 用來配置核心線程數(shù)空閑時 keep alive 的時長褒侧,默認為 1 mins。這項配置一般不需要修改谊迄。
  4. withMaxQueueSize(-1) 用來配置線程池任務隊列的大小闷供,默認值為 -1。當使用 -1 時统诺,SynchronousQueue 將被使用歪脏,即意味著其實這個隊列只是一個交換器,任務將被直接交給工作線程處理粮呢。如果工作線程不足婿失,那任務將被拒絕;如果使用任何正整數(shù)啄寡,LinkedBlockingQueue 將被使用豪硅。

Command Properties

這部分是和命令執(zhí)行直接相關的配置,包括隔離策略挺物、超時時間懒浮、Fallback 相關配置。接下來介紹幾個主要的配置:

隔離策略

默認的隔離策略是實現(xiàn)線程池隔離识藤,另外一種隔離策略是 Semaphore砚著。Instance 默認配置可使用如下方法設置:

HystrixCommandProperties.Setter().withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)

這項配置通常不用配置

超時時間

默認時間是1s次伶,單位是毫秒。Instance 默認配置可以使用如下方法設置:

.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(100))

這項配置比較重要稽穆,后文還會詳細介紹如何調(diào)配這個參數(shù)冠王。

Fallback 并發(fā)度

在 Instance 默認配置中是通過如下代碼設置的:

super(Setter.withGroupKey(BASIC_USAGE_GROUP)
    .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
        .withFallbackIsolationSemaphoreMaxConcurrentRequests(10)
    )
);

默認值為 10。因為 getFallback() 方法是和 run() 方法使用同一個線程池執(zhí)行的秧骑,并且不受線程超時時間限制,并發(fā)過高會影響主邏輯的執(zhí)行扣囊,所有需要控制并發(fā)量乎折。如果 getFallback() 執(zhí)行速度很快仿便,那不用修改此值扁耐。如果 getFallback() 中執(zhí)行一個較為耗時的操作,那就需要考慮修改此值(或再通過另一個 HystrixCommand 調(diào)用挣柬,后續(xù)文章會詳細解釋)惕虑。

五坟冲、小結

本文介紹了 Hystrix 的基本使用方式,看完此文后溃蔫,讀者應該能通過使用 Hystrix 使得自己的應用具備初步的熔斷降級功能健提。下一篇文章將介紹 Hystrix 監(jiān)控相關的內(nèi)容。

六伟叛、參考

文章

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末私痹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子统刮,更是在濱河造成了極大的恐慌紊遵,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侥蒙,死亡現(xiàn)場離奇詭異暗膜,居然都是意外死亡,警方通過查閱死者的電腦和手機鞭衩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門学搜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人论衍,你說我怎么就攤上這事恒水。” “怎么了饲齐?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵钉凌,是天一觀的道長。 經(jīng)常有香客問我捂人,道長御雕,這世上最難降的妖魔是什么矢沿? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮酸纲,結果婚禮上捣鲸,老公的妹妹穿的比我還像新娘。我一直安慰自己闽坡,他們只是感情好栽惶,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著疾嗅,像睡著了一般外厂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上代承,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天汁蝶,我揣著相機與錄音,去河邊找鬼论悴。 笑死掖棉,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的膀估。 我是一名探鬼主播幔亥,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼察纯!你這毒婦竟也來了紫谷?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤捐寥,失蹤者是張志新(化名)和其女友劉穎笤昨,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體握恳,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡瞒窒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了乡洼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片崇裁。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖束昵,靈堂內(nèi)的尸體忽然破棺而出拔稳,到底是詐尸還是另有隱情,我是刑警寧澤锹雏,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布巴比,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏轻绞。R本人自食惡果不足惜采记,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望政勃。 院中可真熱鬧唧龄,春花似錦、人聲如沸奸远。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽懒叛。三九已至丸冕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芍瑞,已是汗流浹背晨仑。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工褐墅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拆檬,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓妥凳,卻偏偏與公主長得像竟贯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子逝钥,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

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