[Soul 源碼之旅] 1.6 Soul數(shù)據(jù)同步 (長輪詢)

1.6.1 背景

我們先來聊一下常用的幾種即時通訊技術(shù)包括 輪詢,長輪詢他匪,和 Websocket 三種割疾。

1.6.1.1 輪詢

輪詢是客戶端每隔一段時間向服務(wù)端發(fā)送請求侧纯,服務(wù)端不管是否又數(shù)據(jù)更新都會直接返回所有數(shù)據(jù),這種方式實現(xiàn)起來很簡單碍讨,而且服務(wù)端無需做任何改造就可以滿足要求治力,但是會占用比較多的內(nèi)存和帶寬,無法承受大量客戶端勃黍。

1.6.1.2 長輪詢

長輪詢是當服務(wù)器收到客戶端發(fā)來的請求后,服務(wù)器端不會直接進行響應(yīng)宵统,而是先將這個請求掛起,然后判斷服務(wù)器端數(shù)據(jù)是否有更新覆获。如果有更新马澈,則進行響應(yīng)瓢省,如果一直沒有數(shù)據(jù),則到達一定的時間限制(服務(wù)器端設(shè)置)才返回箭券。相比輪詢净捅,長輪詢主要優(yōu)點是可以減少帶寬,但是服務(wù)端需進行一定的改造辩块。

1.6.1.2 websocket

websocket 是一種比較新的網(wǎng)絡(luò)協(xié)議蛔六,它是全雙工的,在第一次客戶端向服務(wù)端發(fā)送Http請求建立鏈接后废亭,客戶端和服務(wù)端就處于平等狀態(tài)国章,可以相互發(fā)送數(shù)據(jù),websocket 相比上面兩種協(xié)議豆村,無論是對服務(wù)器的CPU和內(nèi)存資源的消耗液兽,還是服務(wù)的響應(yīng)及時性都要更好,但是需要服務(wù)器做的變動比較多掌动,還需要又支持 websocket 的客戶端四啰。

1.6.2 soul Bootstrap

由于是客戶端發(fā)起請求,我們先來看一下Bootstrap 客戶端粗恢。我們還是根據(jù) 引入的 starter 追蹤到 HttpSyncDataConfiguration 這個配置類柑晒,HttpSyncDataConfiguration 主要是初始化類 httpSyncDataService 這個bean。


HttpSyncDataConfiguration

httpSyncDataService 的初始化主要做了三件事眷射,首先是初始化了所有的插件的 subscriber 訂閱者匙赞,初始化 httpClinet 使用的是 OkHttp3ClientHttpRequestFactory 作為一個 Restemplate ,后面可以直接通過操作 Restemplate 進行輪詢妖碉,最終調(diào)用start 方法涌庭。


image.png

start 方法先判斷當前狀態(tài)是否處于運行狀態(tài),保證每次只有一個客戶端在輪詢欧宜。
image.png

接著調(diào)用 /configs/fetch 接口先拿回全量的數(shù)據(jù)坐榆,然后更新。


image.png

這里有個有趣的地方冗茸,我們看 DataRefreshFactory 的 excite 方法猛拴,這里主要是通過stream 的 foreach 方法進行遍歷,但是這里使用了一個 boolean 數(shù)組蚀狰,但是只有一個元素愉昆,為什么呢,因為 lamb 表達式要求里面的所有元素都是 final 的麻蹋,final 就意味著對這個元素的操作是線程安全的跛溉。但是假如是一個 final 的 boolean 那不是無法修改狀態(tài)了嗎,所以這里使用了一個看起來很奇怪的 boolean 數(shù)組。


image.png

接著 bootsrapt 啟動一個 ThreadPoolExecutor 線程池 芳室,主要是執(zhí)行定時刷新任務(wù)专肪,這個線程池為每個 soul admin 服務(wù)端建立一個定時任務(wù) HttpLongPollingTask ,所以我們知道 soul admin 和 soul bootstrap 是可以使用一個集群提供高可用保證的堪侯。
在定時任務(wù)中主要是先判斷目前是處于運行中嚎尤,是則進行長輪詢,假如輪詢失敗則重試伍宦,重試超過三次就睡眠 5 min芽死。


image.png

doLongPolling 首先為每個需要輪詢的數(shù)據(jù)的MD5值和最后修改時間用逗號拼接作為請求參數(shù),請求服務(wù)端次洼。/configs/listener 接口关贵,然后將拿到的數(shù)據(jù)更新到內(nèi)存中。
doLongPolling

image.png

1.6.3 soul admin
我們接著看 /configs/listener 接口 卖毁, 這里也是調(diào)用 doLongPolling 方法揖曾。


doLongPolling

它先比較請求的MD5值和當前的配置是否相等和最后修改時間和當前的配置是否相同,假如不同亥啦,則返回該配置組炭剪,假如都相同,這里會先取一把鎖翔脱,然后從數(shù)據(jù)庫里面更新最新的數(shù)據(jù)到內(nèi)存中念祭,這里主要是為了多個 soul admin 假如其中一個更新了,其他的也能同步更新碍侦,很多人會想問,這里數(shù)據(jù)是使用 concurrentHasmap 進行存儲隶糕,為什么還需要加鎖瓷产,這里作者解釋,主要是因為存在多個 soul web 的話枚驻,可能存在同時向數(shù)據(jù)庫請求濒旦,數(shù)據(jù)庫的瞬時壓力增大,這種情況很好理解再登,就像我們設(shè)置 redis 的 key 一樣尔邓,不能同時設(shè)置同個過期時間,否則很容易造成緩存穿透和甚至緩存雪崩锉矢。
image.png

這里拿到所有已經(jīng)更新的組信息返回梯嗽。
compareChangedGroup

這里假如有數(shù)據(jù)更新則立即返回數(shù)據(jù)。假如沒有數(shù)據(jù)則調(diào)用 request.startAsync() 方法沽损,這個是什么意思呢灯节,它的作用是HTTP請求不再綁定到HTTP線程,這使我們以后可以使用更少的線程來處理它,我們拿到 asynccontext 后發(fā)給我們的線程池炎疆,這里處理該 http 請求的線程就完成了此次請求卡骂,后續(xù)需要發(fā)送數(shù)據(jù)給客戶端只需要線程池進行通過操作 asynccontext 實現(xiàn)。
longpoll

最終這里通過線程池的schedule方法形入,設(shè)置延時時長全跨,到預定時間后查看緩存數(shù)據(jù)是否有更新,有則返回給客戶端亿遂。
image.png

這里調(diào)用 asyncContext.complete() 整個調(diào)用才算結(jié)束浓若。
sendResponse

1.6.3 總結(jié)

這一期最精彩的莫過于對request.startAsync()對運用,這里假如直接阻塞當前線程崩掘,我們知道 tomcat 處理http 請求對線程是有限的七嫌,直接阻塞假如 soul bootstrap 很多會耗盡請求線程池。這里直接放入 一個調(diào)度線程池苞慢, 這個線程池只有一個線程诵原,當很多請求進來,他會先將它放入 BlockQueue 中挽放,然后一個個處理绍赛,減少了線程池的開銷。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辑畦,一起剝皮案震驚了整個濱河市吗蚌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纯出,老刑警劉巖蚯妇,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異暂筝,居然都是意外死亡箩言,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門焕襟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陨收,“玉大人,你說我怎么就攤上這事鸵赖∥皲觯” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵它褪,是天一觀的道長饵骨。 經(jīng)常有香客問我,道長茫打,這世上最難降的妖魔是什么宏悦? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任镐确,我火速辦了婚禮,結(jié)果婚禮上饼煞,老公的妹妹穿的比我還像新娘源葫。我一直安慰自己,他們只是感情好砖瞧,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布息堂。 她就那樣靜靜地躺著,像睡著了一般块促。 火紅的嫁衣襯著肌膚如雪荣堰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天竭翠,我揣著相機與錄音振坚,去河邊找鬼。 笑死斋扰,一個胖子當著我的面吹牛渡八,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播传货,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼屎鳍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了问裕?” 一聲冷哼從身側(cè)響起逮壁,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎粮宛,沒想到半個月后窥淆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡巍杈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年忧饭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秉氧。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蜒秤,靈堂內(nèi)的尸體忽然破棺而出汁咏,到底是詐尸還是另有隱情,我是刑警寧澤作媚,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布攘滩,位于F島的核電站,受9級特大地震影響纸泡,放射性物質(zhì)發(fā)生泄漏漂问。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蚤假。 院中可真熱鬧栏饮,春花似錦、人聲如沸磷仰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽灶平。三九已至伺通,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間逢享,已是汗流浹背罐监。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瞒爬,地道東北人弓柱。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像疮鲫,于是被迫代替她去往敵國和親吆你。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

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