聊聊高并發(fā)之隔離術(shù)

隔離是指將系統(tǒng)或資源分割開,系統(tǒng)隔離是為了在系統(tǒng)發(fā)生故障時能限定傳播范圍和影響范圍,即發(fā)生故障后不會出現(xiàn)滾雪球效應(yīng)忆嗜,從而保證只有出問題的服務(wù)不可用己儒,其他服務(wù)還是可用的;而資源隔離有臟數(shù)據(jù)隔離捆毫、通過隔離后減少資源競爭提升性能等闪湾。我遇到的比較多的隔離手段有線程隔離、進(jìn)程隔離绩卤、集群隔離途样、機(jī)房隔離、讀寫隔離濒憋、動靜隔離何暇、爬蟲隔離等。而出現(xiàn)系統(tǒng)問題時可以考慮負(fù)載均衡路由凛驮、自動/手動切換分組或者降級等手段來提升可用性裆站。

線程隔離

線程隔離主要有線程池隔離,在實際使用時我們會把請求分類黔夭,然后交給不同的線程池處理宏胯,當(dāng)一種業(yè)務(wù)的請求處理發(fā)生問題時,不會將故障擴(kuò)散到其他線程池本姥,從而保證其他服務(wù)可用肩袍。

我們會根據(jù)服務(wù)等級劃分兩個線程池,以下是池的抽象:

<pre style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 15px; line-height: 1.75; overflow: auto; position: relative; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;"><bean id="zeroLevelAsyncContext" class="com.jd.noah.base.web.DynamicAsyncContext" destroy-method="stop">
    <property name="asyncTimeoutInSeconds" value="${zero.level.request.async.timeout.seconds}"/>
    <property name="poolSize" value="${zero.level.request.async.pool.size}"/>
    <property name="keepAliveTimeInSeconds" value="${zero.level.request.async.keepalive.seconds}"/>
    <property name="queueCapacity" value="${zero.level.request.async.queue.capacity}"/>
</bean>
<bean id="oneLevelAsyncContext" class="com.jd.noah.base.web.DynamicAsyncContext" destroy-method="stop">
    <property name="asyncTimeoutInSeconds" value="${one.level.request.async.timeout.seconds}"/>
    <property name="poolSize" value="${one.level.request.async.pool.size}"/>
    <property name="keepAliveTimeInSeconds" value="${one.level.request.async.keepalive.seconds}"/>
    <property name="queueCapacity" value="${one.level.request.async.queue.capacity}"/>
</bean></pre>

進(jìn)程隔離

在公司發(fā)展初期婚惫,一般是先進(jìn)行從0到1了牛,不會一上來就進(jìn)行系統(tǒng)的拆分,這樣就會開發(fā)出一些比較大而全的系統(tǒng)辰妙,系統(tǒng)中的一個模塊/功能出現(xiàn)問題鹰祸,整個系統(tǒng)就不可用了。首先想到的解決方案是通過部署多個實例密浑,然后通過負(fù)載均衡進(jìn)行路由轉(zhuǎn)發(fā)蛙婴,但是這種情況無法避免某個模塊因BUG而出現(xiàn)如OOM導(dǎo)致整個系統(tǒng)不可用的風(fēng)險。因此此種方案只是一個過渡尔破,較好的解決方案是通過將系統(tǒng)拆分為多個子系統(tǒng)來實現(xiàn)物理隔離街图。通過進(jìn)程隔離使得某一個子系統(tǒng)出現(xiàn)問題不會影響到其他子系統(tǒng)。

集群隔離

隨著系統(tǒng)的發(fā)展懒构,單實例服務(wù)無法滿足需求了餐济,此時需要服務(wù)化技術(shù),通過部署多個服務(wù)胆剧,形成服務(wù)集群來提升系統(tǒng)容量絮姆,如下圖所示

隨著調(diào)用方的增多醉冤,當(dāng)秒殺服務(wù)被刷會影響到其他服務(wù)的穩(wěn)定性,此時應(yīng)該考慮為秒殺提供單獨的服務(wù)集群篙悯,即為服務(wù)分組蚁阳,從而當(dāng)某一個分組出現(xiàn)問題不會影響到其他分組,從而實現(xiàn)了故障隔離鸽照,如下圖所示

比如注冊生產(chǎn)者時提供分組名:

<pre style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 15px; line-height: 1.75; overflow: auto; position: relative; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;"><jsf:provider id="myService" interface="com.jd.MyService" alias="${分組名}" ref="myServiceImpl"/></pre>

消費(fèi)時使用相關(guān)的分組名即可:

<pre style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 15px; line-height: 1.75; overflow: auto; position: relative; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;"><jsf:consumer id="myService" interface="com.jd.MyService" alias="${分組名}"/></pre>

機(jī)房隔離

隨著對系統(tǒng)可用性的要求螺捐,會進(jìn)行多機(jī)房部署,每個機(jī)房的服務(wù)都有自己的服務(wù)分組矮燎,本機(jī)房的服務(wù)應(yīng)該只調(diào)用本機(jī)房服務(wù)定血,不進(jìn)行跨機(jī)房調(diào)用;其中一個機(jī)房服務(wù)發(fā)生問題時可以通過DNS/負(fù)載均衡將請求全部切到另一個機(jī)房诞外;或者考慮服務(wù)能自動重試其他機(jī)房的服務(wù)從而提升系統(tǒng)可用性澜沟。

一種辦法是根據(jù)IP(不同機(jī)房IP段不一樣)自動分組,還一種較靈活的辦法是通過在分組名中加上機(jī)房名解決:

<pre style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 15px; line-height: 1.75; overflow: auto; position: relative; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;"><jsf:provider id="myService" interface="com.jd.MyService" alias="${分組名}-${機(jī)房}" ref="myServiceImpl"/></pre>

<pre style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 15px; line-height: 1.75; overflow: auto; position: relative; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;"><jsf:consumer id
                        ="myService" interface="com.jd.MyService" alias
                            ="${分組名}-${機(jī)房}"/></pre>

讀寫隔離

如下圖所示浅乔,通過主從模式將讀和寫集群分離倔喂,讀服務(wù)只從從Redis集群獲取數(shù)據(jù),當(dāng)主Redis集群出現(xiàn)問題時靖苇,從Redis集群還是可用的席噩,從而不影響用戶訪問;而當(dāng)從Redis集群出現(xiàn)問題時可以進(jìn)行其他集群的重試贤壁。

<pre style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 15px; line-height: 1.75; overflow: auto; position: relative; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">--先讀取從
status, resp = slave_get(key)
if status == STATUS_OK then
    return status, value
end
--如果從獲取失敗了悼枢,從主獲取
status, resp = master_get(key)</pre>

動靜隔離

當(dāng)用戶訪問如結(jié)算頁時,如果JS/CSS等靜態(tài)資源也在結(jié)算頁系統(tǒng)中時脾拆,很可能因為訪問量太大導(dǎo)致帶寬被打滿導(dǎo)致出現(xiàn)不可用馒索。

因此應(yīng)該將動態(tài)內(nèi)容和靜態(tài)資源分離,一般應(yīng)該將靜態(tài)資源放在CDN上名船,如下圖所示

爬蟲隔離

在實際業(yè)務(wù)中我們曾經(jīng)統(tǒng)計過一些頁面型應(yīng)用的爬蟲比例绰上,爬蟲和正常流量的比例能達(dá)到5:1,甚至更高渠驼。而一些系統(tǒng)是因為爬蟲訪問量太大而導(dǎo)致服務(wù)不可用蜈块;一種解決辦法是通過限流解決;還一種解決辦法是在負(fù)載均衡層面將爬蟲路由到單獨集群迷扇,從而保證正常流量可用百揭,爬蟲流量盡量可用。

比如最簡單的使用Nginx可以這樣配置:

<pre style="font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 15px; line-height: 1.75; overflow: auto; position: relative; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">set flag 0; if (http_user_agent ~* "spider") {
set flag "1"; } if(flag = "0") {
//代理到正常集群
}
if ($flag = "1") {
//代理到爬蟲集群
}</pre>

實際場景我們使用了Openresty蜓席,不僅僅對爬蟲user-agent過濾器一,還會過濾一些惡意IP(統(tǒng)計IP訪問量,配置閥值)厨内,將他們分流到固定分組祈秕。還有一種辦法是種植Cookie渺贤,訪問特殊服務(wù)前先種植Cookie,訪問服務(wù)時驗證該Cookie踢步,如果沒有或者不對可以考慮出驗證碼或者分流到固定分組癣亚。

熱點隔離

秒殺丑掺、搶購屬于非常合適的熱點例子获印;對于這種熱點是能提前知道的,所以可以將秒殺和搶購做成獨立系統(tǒng)或服務(wù)進(jìn)行隔離街州,從而保證秒殺/搶購流程出現(xiàn)問題不影響主流程兼丰。

還存在一些熱點可能是因為價格或突發(fā)事件引起的;對于讀熱點我使用多級緩存搞定唆缴;而寫熱點我們一般通過緩存+隊列模式削峰鳍征,可以參考《前端交易型系統(tǒng)設(shè)計原則》。

資源隔離

最常見的資源如磁盤面徽、CPU艳丛、網(wǎng)絡(luò);對于寶貴的資源都會存在競爭問題趟紊。

在《構(gòu)建需求響應(yīng)式億級商品詳情頁》中我們使用JIMDB數(shù)據(jù)同步時要dump數(shù)據(jù)氮双,SSD盤容量用了50%以上,dump到同一塊磁盤時遇到了容量不足的問題霎匈,我們通過單獨掛一塊SAS盤來專門同步數(shù)據(jù)戴差。還有如使用Docker容器時,有的容器寫磁盤非常頻繁铛嘱,因此要考慮為不同的容器掛載不同的磁盤暖释。

默認(rèn)CPU的調(diào)度策略在一些追求極致性能的場景下可能并不太適合,我們希望通過綁定CPU到特定進(jìn)程來提升性能墨吓。如我們一臺機(jī)器會啟動很多個Redis實例球匕,通過將CPU通過taskset綁定到Redis實例上可以提升一些性能;還有Nginx提供了worker_processes和worker_cpu_affinity來綁定CPU帖烘。還有如系統(tǒng)網(wǎng)絡(luò)應(yīng)用比較繁忙的話亮曹,可以考慮綁定網(wǎng)卡IRQ到指定的CPU來提升系統(tǒng)處理中斷的能力,從而提升性能蚓让。

還有如大數(shù)據(jù)計算集群乾忱、數(shù)據(jù)庫集群應(yīng)該和應(yīng)用集群隔離到不同的機(jī)架,并盡量隔離網(wǎng)絡(luò)历极;因為大數(shù)據(jù)計算或數(shù)據(jù)庫同步時時會有比較大的網(wǎng)絡(luò)帶寬窄瘟,可能擁塞網(wǎng)絡(luò)導(dǎo)致應(yīng)用響應(yīng)慢。

還有一些其他類似的隔離術(shù)趟卸,如環(huán)境隔離(測試環(huán)境蹄葱、預(yù)發(fā)布環(huán)境/灰度環(huán)境氏义、正式環(huán)境)、壓測隔離(真實數(shù)據(jù)图云、壓測數(shù)據(jù)隔離)惯悠、ABTest(為不同的用戶提供不同版本的服務(wù))、緩存隔離(有些系統(tǒng)混用緩存竣况,而有些系統(tǒng)會扔大字節(jié)值到如Redis克婶,造成Redis慢查詢)、查詢隔離(簡單丹泉、批量情萤、復(fù)雜條件查詢分別路由到不同的集群)等。通過隔離后可以將風(fēng)險降低到最低摹恨、性能提升至最優(yōu)筋岛。

原文鏈接:mp.weixin.qq.com
需要Java資料的,歡迎加群957734884晒哄。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末睁宰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子寝凌,更是在濱河造成了極大的恐慌柒傻,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件硫兰,死亡現(xiàn)場離奇詭異诅愚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)劫映,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門违孝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泳赋,你說我怎么就攤上這事雌桑。” “怎么了祖今?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵校坑,是天一觀的道長。 經(jīng)常有香客問我千诬,道長耍目,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任徐绑,我火速辦了婚禮邪驮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘傲茄。我一直安慰自己毅访,他們只是感情好沮榜,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著喻粹,像睡著了一般蟆融。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上守呜,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天型酥,我揣著相機(jī)與錄音,去河邊找鬼弛饭。 笑死冕末,一個胖子當(dāng)著我的面吹牛萍歉,可吹牛的內(nèi)容都是我干的侣颂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼枪孩,長吁一口氣:“原來是場噩夢啊……” “哼憔晒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蔑舞,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拒担,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后攻询,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體从撼,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年钧栖,在試婚紗的時候發(fā)現(xiàn)自己被綠了低零。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡拯杠,死狀恐怖掏婶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情潭陪,我是刑警寧澤雄妥,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站依溯,受9級特大地震影響老厌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜黎炉,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一枝秤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拜隧,春花似錦宿百、人聲如沸趁仙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雀费。三九已至,卻和暖如春痊焊,著一層夾襖步出監(jiān)牢的瞬間盏袄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工薄啥, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留辕羽,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓垄惧,卻偏偏與公主長得像刁愿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子到逊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

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