自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

盤一盤這個沒資格出現(xiàn)在面試環(huán)節(jié)的場景題

開發(fā) 前端
直接把你的核心線程都占滿了,剩下的兩筆對應(yīng) B 和 C 通道的數(shù)據(jù)就在隊列里面排著隊,等著。你說這個合不合理?非常不合理,對不對?

你好呀,我是歪歪。

前兩天在一個技術(shù)群里看到有人拋出一張圖片,提出了這樣的一個問題:

請教一下,線程池可以做到根據(jù)任務(wù)的類型,來指定特定線程執(zhí)行嗎?

圖片圖片

了解了一下背景,是批量任務(wù)觸發(fā),從訂單表中查詢出“處理中”狀態(tài)的訂單,訂單可能屬于不同的通道,所以需要調(diào)用不同通道的接口。

現(xiàn)在的方案是把訂單查出來之后,往線程池里面扔,在異步任務(wù)里面判斷當(dāng)前訂單是屬于哪個通道,就調(diào)用哪個通道的查詢接口:

圖片圖片

這是常規(guī)做法,看起來沒有毛病。

但是現(xiàn)在提問的這個哥們遇到了一個問題:有一個通道的查詢接口特別慢,會占著線程池里面的線程資源,影響了其他兩個通道的訂單查詢。

舉個極端的例子,比如你的線程池核心線程數(shù)就三個。

假設(shè)一共有 5 筆數(shù)據(jù),前 3 筆是通道 A 的,后面兩筆分別是通道 B 和通道 C 的。

結(jié)果現(xiàn)在通道 A 出問題了:

圖片圖片

直接把你的核心線程都占滿了,剩下的兩筆對應(yīng) B 和 C 通道的數(shù)據(jù)就在隊列里面排著隊,等著。

你說這個合不合理?

非常不合理,對不對?

但是這個問題確實也是很常規(guī),常規(guī)到它甚至沒有資格作為一個場景面試題出現(xiàn)在面試環(huán)節(jié)中。

問題在于不同的通道在共用同一個線程池,從而導(dǎo)致的相互影響。所以解決思路主要就是怎么把資源隔離開來。

一般來說,大家能想到的第一個解決方案就是用 MQ 嘛:

圖片圖片

利用不同的隊列,天然就把不同通道的訂單給區(qū)分開了,在監(jiān)聽側(cè)各自處理各自通道的數(shù)據(jù),這樣就達(dá)到了資源隔離的效果。

這個方案應(yīng)該是很常規(guī)了,但是這個常規(guī)方案立馬就被斃了。

因為:

圖片圖片

需要注意的是,他這里說的“系統(tǒng)內(nèi)部”是指同一個微服務(wù),也就是不允許一個微服務(wù)使用 MQ 來做“自產(chǎn)自銷”。

我個人認(rèn)為是“自產(chǎn)自銷”沒有任何問題的,在這個場景下我完全可以借助它的特性幫我做數(shù)據(jù)分隔、異步處理數(shù)據(jù),而且代碼簡單,邏輯清晰。

但是既然是公司規(guī)定,可能有一些因地制宜的考慮,我們也不好去做過多的批判。

反正就是 MQ 可以解決這個問題,但是老板并不采取這個方案。

沒關(guān)系,小腦殼一轉(zhuǎn),大多數(shù)同學(xué)就能立馬就掏出了另外一個解決方案。

你前面出問題的原因不是因為不同的通道在共用同一個線程池嗎?

那很簡單,每個通道各自搞一個線程池。然后和 MQ 的方案類似,根據(jù)不同的通道扔到對應(yīng)的線程池中去,自己玩自己的:

這樣即使某個通道出問題了,由于在線程池層面做了線程資源隔離,所以也不影響另外的通道進(jìn)行數(shù)據(jù)處理。

這個就是線程池隔離的方案。

其實關(guān)于這個方案,我當(dāng)時還想到了另外一種原理一致,實現(xiàn)形式不一樣,但是最終被認(rèn)為是比較 low 的一個回答。

因為他拋出的這個圖片,我第一眼理解錯了,我以為是按照通道分組,然后用單線程一個個的去調(diào)用查詢接口,避免并發(fā)調(diào)用:

圖片圖片

所以我提到了一個叫做 KeyAffinityExecutor 的魔改線程池:

圖片圖片

這個線程池,它有一個比較厲害的特性,可以確保投遞進(jìn)來的任務(wù)按某個維度劃分出任務(wù),然后按照任務(wù)提交的順序依次執(zhí)行。這個線程池可以通過并行處理(多個線程)來提高吞吐量、又能保證一定范圍內(nèi)的任務(wù)按照嚴(yán)格的先后順序來運(yùn)行。

對比到當(dāng)前的這個問題中。

可以按照通道維度進(jìn)行任務(wù)劃分,然后把任務(wù)往線程池扔的時候,就會被分配到不同的線程中去。

關(guān)于這個線程池,我之前寫了這篇文章,有興趣的可以去了解一下,不贅述了:《看到一個魔改線程池,面試素材加一!》

本質(zhì)上還是線程池隔離的思路,只不過一個是分多個不同的業(yè)務(wù)線程池,線程池和業(yè)務(wù)綁定。一個是一個大線程池里面包了多個線程池,線程池可以通過分配規(guī)則的方式指定。

同一個思路的不同實現(xiàn)方案而已。

但是為什么我說我提出的這個魔改線程池的方案 low 呢?

因為人家只是需要分組的特性,而不需要“按照任務(wù)提交的順序依次執(zhí)行”的特性。

反而會出現(xiàn)如果一個通道的訂單多,只有一個線程來處理,導(dǎo)致性能不夠,任務(wù)堆積的情況。

但是,話說回來,你也可以魔改一下這個魔改線程池,把里面的小線程池的核心線程數(shù)搞多點,就行了。

總之,都是線程池隔離的思路。

好了,這個方案我又講完了,誰贊成,誰反對?

看著沒有任何問題,但是實際情況是:

圖片圖片

臥槽,50 多個?

這特么的,簡歷還給我,我不面了,告辭。

確實,如果是只有三個通道,或者多說點,五個通道嘛,我覺得用上面這個方案做線程池維度的隔離,都是可以接受的。

但實際情況是 50 多個通道,一想起項目里面有 50 多個線程池在跑,這個就有點難受了。

好了,現(xiàn)在 MQ 和線程池隔離的方案都被否決了,接下來的思路是什么?

沒有思路沒有關(guān)系,我們再來讀讀題:批量任務(wù)觸發(fā),從訂單表中查詢出“處理中”狀態(tài)的訂單,訂單可能屬于不同的通道,所以需要調(diào)用不同通道的接口。但是某個通道慢,導(dǎo)致影響了其他通道訂單的查詢。

問怎么辦?

某個通道慢,該怎么辦?

有的通道慢,有的通道快,我該怎么辦?

等等...

前面我們按照通道維度分線程池被否了的原因是通道太多了。

但是其實針對響應(yīng)快的通道,我們完全不需要做線程池隔離,他們完全可以使用同一個線程池嘛,反正都是唰唰唰的就查回來了。

所以,我們只需要搞兩個線程池,一個處理通道響應(yīng)快的,比如把接口調(diào)用的超時時間設(shè)置為 1s。另外一個處理通道響應(yīng)慢的,超時時間直接拉滿到 30s,自己慢慢玩去:

圖片圖片

至于怎么去判斷通道到底是快是慢呢?

這里又可以大致分為三個不同的方案了。

第一個方案就是已知某幾個通道是慢的,那就代碼里面寫硬編碼都行。雖然不優(yōu)雅,但是這確實也是一個在實際生產(chǎn)中常常被提及的一個快速解決問題的方案。

第二個方案就是配置化,可以做個配置表,來配置通道的快慢標(biāo)識。程序里面根據(jù)當(dāng)前訂單的通道,來表里面獲取當(dāng)前通道的快慢標(biāo)識,從而把訂單扔到不同的線程池中去。

在這個方案中,用配置表代替了硬編碼,但是還是需要人工基于線下溝通或者數(shù)據(jù)監(jiān)控的方式去調(diào)整通道的快慢標(biāo)識。

你知道的,線上程序這玩意,一旦涉及到人工介入,就遭老罪了,很不爽。

所以這個方案,有一點優(yōu)雅,但是不多。

第三個方案就是配置化加自動化這一套組合拳。

配置化還是指前面提到的配置表。

但是這個表中通道的快慢標(biāo)識,就不需要人工來介入了,完全由程序自己收集信息,進(jìn)行判斷。

比如,我們可以假設(shè)一開始的時候所有的通道都能快速響應(yīng)。但是突然某個通道開始“扯拐”,響應(yīng)時長出現(xiàn)波動,1s 內(nèi)沒有響應(yīng)成功,那么這個任務(wù)就會超時,就可以把這個任務(wù)扔到慢通道線程池中去處理,同時對該通道的失敗次數(shù)進(jìn)行記錄。

當(dāng)某個時間段失敗次數(shù)超過某個閾值之后,則在配置表中標(biāo)識該通道為慢通道。

這樣當(dāng)下一個屬于該通道的訂單過來時,就會直接被扔到慢通道線程池中去。

這樣,就由程序完成了通道由“快標(biāo)識”到“慢標(biāo)識”的處理。

那么當(dāng)這個通道的問題解決之后,它又變成一個快通道時,怎么去修改它在配置表中的標(biāo)識呢?

很簡單,同樣的邏輯,在慢通道線程池處理的過程中,記錄某個時間段某個通道的平均響應(yīng)時長,如果低于指定閾值,比如 1s,則在配置表中重新標(biāo)識該通道為快通道。

整個過程,不管標(biāo)識怎么變化,都是基于程序自動的數(shù)據(jù)統(tǒng)計來的,完全不需要人工介入。

甚至你還可以加一個邏輯:當(dāng)配置表中的通道都是快通道時,兩個線程池都可以用起來,實現(xiàn)資源利用的最大化。

優(yōu)雅,非常優(yōu)雅。

至于怎么去統(tǒng)計線程池中的任務(wù)“某個時間段失敗次數(shù)”和“某個時間段某個通道的平均響應(yīng)時長”這樣的統(tǒng)計信息,在線程池里面,專門留了這兩個方法給你去在任務(wù)執(zhí)行之前和之后搞事情,完全可以基于這兩個方法做一些統(tǒng)計工作:

java.util.concurrent.ThreadPoolExecutor#runWorker

圖片圖片

圖片圖片

就目前提出的方案來說,把通道分為快慢通道,然后劃分為線程池是最滿足提問者的需求的。

最后應(yīng)該就拿著這個方案去匯報了。

匯報題目我都幫忙想好了:

《基于通道關(guān)鍵指標(biāo)收集分析的全自適應(yīng)、高敏感度、資源利用最大化的調(diào)度方案匯報》

剩下的,就看你怎么去吹了。

除去前面的方案外,其實我還想到一個“比較奇葩”的解決方案。

因為他的業(yè)務(wù)場景是定時任務(wù)嘛,所以我想起了之前寫過的這篇文章:《又被奪命連環(huán)問了!從一道關(guān)于定時任務(wù)的面試題說起?!?/p>

既然能區(qū)分出來通道的快慢,那么在定時任務(wù)啟動之后,我們就可以把“快慢標(biāo)識”傳遞到服務(wù)器中去,服務(wù)器就能把訂單分為快慢兩大類,然后一臺機(jī)器處理通道慢的訂單數(shù)據(jù),一臺處理快的:

圖片圖片

這樣我就能從服務(wù)器這個物理層面就把數(shù)據(jù)區(qū)分開了。

所以只要能標(biāo)識開區(qū)分?jǐn)?shù)據(jù),那么理論上不僅可以在代碼中區(qū)分,也可以往上抽離一層,通過服務(wù)器維度區(qū)分。

但是好處是什么呢?

呃...

看起來確實沒什么好處,只是這個方案比較奇葩,一般沒人想到,我就是順便提一嘴,主要是顯擺一下。

不顯擺一下,裝裝逼,總感覺不得勁。

類似的場景

基于提問者的這個問題,歪師傅也想起了兩個類似的場景。

一個是我參與開發(fā)過的一個對客發(fā)送短信的消息系統(tǒng),簡化一下整個流程大概是這樣的:

圖片圖片

上面這個圖片會出現(xiàn)什么問題呢?

就是消息堆積。

當(dāng)某個業(yè)務(wù)系統(tǒng)調(diào)用短信發(fā)送接口,批量發(fā)送消息的時候,比如發(fā)送營銷活動時,大量的消息就在隊列里面堆著,慢慢消費。

其實堆積也沒有關(guān)系,畢竟?fàn)I銷活動的實時性要求不是那么高,不要求立馬發(fā)送到客戶手機(jī)上去。

但是,如果在消息堆積起來之后,突然有用戶申請了驗證碼短信呢?

圖片圖片

需要把前面堆積的消費完成后,才會發(fā)送驗證碼短信,這個已經(jīng)來不及了,甚至驗證碼已經(jīng)過期很久了你才發(fā)過去。

客戶肯定會罵娘,因為獲取不到驗證碼,他就不能進(jìn)行后續(xù)業(yè)務(wù)。

如果大量客戶因為收不到驗證碼不能進(jìn)行后續(xù)業(yè)務(wù),引起群體性的客訴,甚至用戶恐慌,這個對于企業(yè)來說是一個非常嚴(yán)重的事件。

怎么辦呢?

解決方案非常簡單,再搞一個“高速”隊列出來:

圖片圖片

驗證碼消息直接扔到“高速”隊列中去,這個隊列專門用來處理驗證碼、動賬通知這一類時效性要求極高的消息,從業(yè)務(wù)場景上分析,也不會出現(xiàn)消息堆積。

不是特別復(fù)雜的方案,大道至簡,問題得到了解決。

類比到前面說的“快慢”線程池,其實是一樣的思想,都是從資源上進(jìn)行隔離。

只不過我說的這個場景更加簡單,不需要去收集信息進(jìn)行動態(tài)判斷。業(yè)務(wù)流程上天然的就能區(qū)分出來,哪些消息實時性比較高,應(yīng)該走“高速”隊列;哪些消息慢慢 發(fā)沒關(guān)系,可以應(yīng)該走“常規(guī)”隊列。

而這個所謂的“高速”和“常規(guī)”,只是開發(fā)人員給一個普通隊列賦予的一個屬性而已,站在 MQ 的角度,這兩個隊列沒有任何區(qū)別。

另外一個場景是我想起了之前寫過的這篇文章:《我試圖給你分享一種自適應(yīng)的負(fù)載均衡?!?/p>

我們還是先看看前面出現(xiàn)的這個圖:

圖片圖片

圖中的線程池,不管是快的還是慢的,本質(zhì)上他們處理的請求都是一樣的,即拿著訂單去對應(yīng)的通道查詢訂單結(jié)果。

那我們是不是可以把這兩個線程池抽象一下,理解為部署了同一個服務(wù)的兩個不同的服務(wù)器,一個服務(wù)器的性能好,一個服務(wù)器的性能差。

現(xiàn)在有一個請求過來了,理論上這兩個服務(wù)器都能處理這個請求,所以我們通過某個邏輯選一個服務(wù)器出來,把請求發(fā)過去。

這個“某個邏輯”不就是我們常說的負(fù)載均衡算法嗎?

負(fù)載均衡算法的算法有很多:

圖片圖片

其中這幾個都是需要統(tǒng)計服務(wù)端的相關(guān)數(shù)據(jù),基于數(shù)據(jù)進(jìn)行分析,最終覺得把當(dāng)前請求發(fā)個哪個服務(wù)器:

圖片圖片

這個邏輯,和我們前面提到的這句話,其實是一脈相承的,都是信息收集、指標(biāo)分析、閾值設(shè)定:

去統(tǒng)計線程池中的任務(wù)“某個時間段失敗次數(shù)”和“某個時間段某個通道的平均響應(yīng)時長”這樣的統(tǒng)計信息

你想想我們最開始的問題是“一個通道慢了,影響了其他通道的數(shù)據(jù),怎么辦?”

現(xiàn)在我?guī)е愠兜搅恕柏?fù)載均衡策略”。

這兩個場景不能說八竿子打不著吧,但是它們確實在一定程度上有相似性,轉(zhuǎn)好幾個彎之后,也能聯(lián)系到一起。

你要是再發(fā)散一點,你甚至能想到 Serverless 的彈性場景,通過收集 CPU、Mem 指標(biāo)、QPS、RT、TCP 連接數(shù)等指標(biāo),進(jìn)行綜合判斷,彈性擴(kuò)容,也無需人工介入,手動擴(kuò)容。

所以,朋友,這個事情告訴我們一個什么道理?

向上抽象問題的能力,把看看似不一樣的場景抽離成類似的問題模型的能力很重要。

還有,“一個通道慢需要進(jìn)行資源隔離”這個問題的關(guān)鍵不在于“一個通道”上,雖然可以在通道層面做隔離,但是這樣并沒有抓住問題的關(guān)鍵。問題的關(guān)鍵在于“通道慢”,所以可以在“快慢”的維度上做隔離,這才是問題的關(guān)鍵。

關(guān)鍵問題,就是要找到問題的關(guān)鍵。

這也是我在這一次群聊的討論中學(xué)習(xí)到的東西。

責(zé)任編輯:武曉燕 來源: why技術(shù)
相關(guān)推薦

2025-01-08 17:20:00

pytho數(shù)據(jù)分組itertools

2022-03-25 13:45:37

黑客網(wǎng)絡(luò)攻擊數(shù)據(jù)泄露

2025-01-08 14:34:58

2012-07-11 13:32:11

虛擬化

2020-06-05 15:48:26

網(wǎng)絡(luò)安全技術(shù)漏洞

2024-07-10 10:04:48

2015-03-02 11:23:51

2012-08-21 15:24:07

騰訊App

2014-01-16 13:36:17

2017-09-28 09:25:50

SQL ServerLinuxWindows

2021-10-29 09:55:20

人工神經(jīng)網(wǎng)絡(luò)

2022-04-12 11:51:24

惡意應(yīng)用木馬程序TeaBot

2010-04-29 11:23:08

Apple

2022-05-07 09:08:13

路由策略網(wǎng)絡(luò)規(guī)劃

2015-09-23 11:43:00

小米副卡虛擬運(yùn)營商

2019-06-21 14:36:11

物聯(lián)網(wǎng)企業(yè)IOT

2022-01-14 11:47:15

UbuntuLTSGNOME 版本

2017-05-18 12:40:44

AlphaGoAI柯潔

2009-09-21 09:42:25

微軟總部美洲獅
點贊
收藏

51CTO技術(shù)棧公眾號