Hystrix源碼分析(三)-信號量

一、概要

hystrix的執(zhí)行隔離策略有兩種。一種是線程池的模式哼拔,另外一種是信號量的模式嚼黔。hystrix默認的策略是線程池的模式细层。

  • 線程池
    對于每個command的執(zhí)行會啟用一個新的線程,同一個command key會使用同一個線程池唬涧,不同的command key會使用不同的線程池就進行隔離疫赎。
    優(yōu)點:由于command的執(zhí)行隔離在不同的線程中,因此某一個command線程執(zhí)行異常不會影響到其它command的執(zhí)行碎节。如果希望使用到異步的方式執(zhí)行捧搞,只能選擇這種模式。
    缺點:由于多了線程的介入狮荔,相當于增加了線程間的上下文切換的成本胎撇。另外如果系統(tǒng)的command key很多,可能會影響到系統(tǒng)的整體性能殖氏。
  • 信號量
    個人理解跟信號量其實沒有太大的關聯性晚树。本質上是跟主線程共用一個線程,只是這里增加了一個最大并發(fā)數的限制(信號量)受葛。
    優(yōu)點:不涉及線程上下文切換题涨。在大部分業(yè)務場景下其實是能滿足的(eg.tomcat單請求單線程的業(yè)務偎谁,command key之間沒有異步執(zhí)行的需求)
    缺點:某一個command執(zhí)行過程中導致線程崩潰會影響到整個流程的執(zhí)行(共享線程)。

二纲堵、源碼分析

  1. 信號量的接口定義
/* package */static interface TryableSemaphore {

        /**
         * Use like this:
         * <p>
         * 
         * <pre>
         * if (s.tryAcquire()) {
         * try {
         * // do work that is protected by 's'
         * } finally {
         * s.release();
         * }
         * }
         * </pre>
         * 
         * @return boolean
         */
        public abstract boolean tryAcquire();

        /**
         * ONLY call release if tryAcquire returned true.
         * <p>
         * 
         * <pre>
         * if (s.tryAcquire()) {
         * try {
         * // do work that is protected by 's'
         * } finally {
         * s.release();
         * }
         * }
         * </pre>
         */
        public abstract void release();

        public abstract int getNumberOfPermitsUsed();

    }

接口的定義很簡單巡雨,上層調用會先tryAcquire獲得信號量,然后通過release方式釋放信號量席函。

  1. 實現類
    實現類有兩種铐望。TryableSemaphoreActual和TryableSemaphoreNoOp。
  • TryableSemaphoreActual
    信號量的實現類茂附。
  • TryableSemaphoreNoOp
    這個實現類相當于不限制正蛙,線程池模式的實現類采用的方式就是這種。
/* package */static class TryableSemaphoreActual implements TryableSemaphore {
        protected final HystrixProperty<Integer> numberOfPermits;
        private final AtomicInteger count = new AtomicInteger(0);

        public TryableSemaphoreActual(HystrixProperty<Integer> numberOfPermits) {
            this.numberOfPermits = numberOfPermits;
        }

        @Override
        public boolean tryAcquire() {
            int currentCount = count.incrementAndGet();
            if (currentCount > numberOfPermits.get()) {
                count.decrementAndGet();
                return false;
            } else {
                return true;
            }
        }

        @Override
        public void release() {
            count.decrementAndGet();
        }

        @Override
        public int getNumberOfPermitsUsed() {
            return count.get();
        }

    }

這個實現類就不多加解釋了营曼,主要是用了AtomicInteger做加減的操作乒验。
3.調用層

private Observable<R> applyHystrixSemantics(final AbstractCommand<R> _cmd) {
       ...

        /* determine if we're allowed to execute */
        if (circuitBreaker.allowRequest()) {
            final TryableSemaphore executionSemaphore = getExecutionSemaphore();
            final AtomicBoolean semaphoreHasBeenReleased = new AtomicBoolean(false);
            final Action0 singleSemaphoreRelease = new Action0() {
                @Override
                public void call() {
                    if (semaphoreHasBeenReleased.compareAndSet(false, true)) {
-- 釋放信號量的操作
                        executionSemaphore.release();
                    }
                }
            };

            final Action1<Throwable> markExceptionThrown = new Action1<Throwable>() {
                @Override
                public void call(Throwable t) {
                    eventNotifier.markEvent(HystrixEventType.EXCEPTION_THROWN, commandKey);
                }
            };
-- 獲取信號量
            if (executionSemaphore.tryAcquire()) {
                try {
                    /* used to track userThreadExecutionTime */
                    executionResult = executionResult.setInvocationStartTime(System.currentTimeMillis());
                    return executeCommandAndObserve(_cmd)
                            .doOnError(markExceptionThrown)
                            .doOnTerminate(singleSemaphoreRelease)
                            .doOnUnsubscribe(singleSemaphoreRelease);
                } catch (RuntimeException e) {
                    return Observable.error(e);
                }
            } else {
                return handleSemaphoreRejectionViaFallback();
            }
        } else {
            return handleShortCircuitViaFallback();
        }
    }

三、總結

在實際的工作中對信號量和線程池的選擇還是要慎重蒂阱,事實上對于一般場景的單請求單線程的業(yè)務锻全,信號量是能夠滿足需求的。
對于需要異步(command并行執(zhí)行)的業(yè)務需要使用線程池的方式來實現录煤。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末鳄厌,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子妈踊,更是在濱河造成了極大的恐慌了嚎,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件廊营,死亡現場離奇詭異歪泳,居然都是意外死亡,警方通過查閱死者的電腦和手機赘风,發(fā)現死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門夹囚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人邀窃,你說我怎么就攤上這事荸哟。” “怎么了瞬捕?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵鞍历,是天一觀的道長。 經常有香客問我肪虎,道長劣砍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任扇救,我火速辦了婚禮刑枝,結果婚禮上香嗓,老公的妹妹穿的比我還像新娘。我一直安慰自己装畅,他們只是感情好靠娱,可當我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著掠兄,像睡著了一般像云。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蚂夕,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天迅诬,我揣著相機與錄音,去河邊找鬼婿牍。 笑死侈贷,一個胖子當著我的面吹牛,可吹牛的內容都是我干的牍汹。 我是一名探鬼主播铐维,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼柬泽,長吁一口氣:“原來是場噩夢啊……” “哼慎菲!你這毒婦竟也來了?” 一聲冷哼從身側響起锨并,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤露该,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后第煮,有當地人在樹林里發(fā)現了一具尸體解幼,經...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年包警,在試婚紗的時候發(fā)現自己被綠了撵摆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡害晦,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情钦讳,我是刑警寧澤银室,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站稻轨,受9級特大地震影響灵莲,放射性物質發(fā)生泄漏。R本人自食惡果不足惜殴俱,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一政冻、第九天 我趴在偏房一處隱蔽的房頂上張望枚抵。 院中可真熱鬧,春花似錦明场、人聲如沸俄精。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽竖慧。三九已至,卻和暖如春逆屡,著一層夾襖步出監(jiān)牢的瞬間圾旨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工魏蔗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留砍的,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓莺治,卻偏偏與公主長得像廓鞠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子谣旁,可洞房花燭夜當晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內容

  • 原文:https://my.oschina.net/7001/blog/1619842 摘要: Hystrix是N...
    laosijikaichele閱讀 4,312評論 0 25
  • 0. Hystrix是什么? Hystrix的本意是指 豪豬 的動物床佳,它身上長滿了很長的較硬的空心尖刺,當受到攻擊...
    亦山札記閱讀 14,847評論 4 36
  • 一、認識Hystrix Hystrix是Netflix開源的一款容錯框架榄审,包含常用的容錯方法:線程池隔離砌们、信號量隔...
    新棟BOOK閱讀 4,045評論 0 19
  • 一、認識Hystrix Hystrix是Netflix開源的一款容錯框架搁进,包含常用的容錯方法:線程池隔離浪感、信號量隔...
    新棟BOOK閱讀 26,479評論 1 37
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,103評論 1 32