目錄
- 1、到底什麼是連接配接?
- 2、為什麼每次發送請求都要建立連接配接?
- 3、長連接配接模式下需要耗費大量資源
- 4、Kafka遇到的問題:應對大量用戶端連接配接
- 5、Kafka的架構實踐:Reactor多路複用
- 6、優化後的架構是如何支撐大量連接配接的
這篇文章,給大家聊聊:如果你設計一個系統需要支撐百萬使用者連接配接,應該如何來設計其高并發請求處理架構?
1、到底什麼是連接配接?
假如說現在你有一個系統,他需要連接配接很多很多的硬體裝置,這些硬體裝置都要跟你的系統來通信。
那麼,怎麼跟你的系統通信呢?
首先,他一定會跟你的系統建立連接配接,然後會基于那個連接配接發送請求給你的系統。
接着你的系統會傳回響應給那個系統,最後是大家一起把連接配接給斷開,釋放掉網絡資源。
是以我們來看一下下面的那個圖,感受一下這個所謂的連接配接到底是個什麼概念。
2、為什麼每次發送請求都要建立連接配接?
但是大家看着上面的那個圖,是不是感覺有一個很大的問題。
什麼問題呢?那就是為啥每次發送請求,都必須要建立一個連接配接,然後再斷開一個連接配接?
要知道,網絡連接配接的建立和連接配接涉及到多次網絡通信,本質是一個比較耗費資源的過程。
是以說咱們完全沒必要每次發送請求都要建立一次連接配接,斷開一次連接配接。
我們完全可以建立好一個連接配接,然後裝置就不停的發送請求過來,系統就通過那個連接配接傳回響應。
大家完全可以多次通過一個連接配接發送請求和傳回響應,這就是所謂的長連接配接。
也就是說,如果你一個連接配接建立之後,然後發送請求,接着就斷開,那這個連接配接維持的時間是很短的,這個就是所謂的短連接配接。
那如果一個裝置跟你的系統建立好一個連接配接,然後接着就不停的通過這個連接配接發送請求接收響應,就可以避免不停的建立連接配接和斷開連接配接的開銷了。
大家看下面的圖,體驗一下這個過程。在圖裡面,兩次連接配接之間,有很多次發送請求和接收響應的過程,這樣就可以利用一個連接配接但是進行多次通信了。
3、長連接配接模式下需要耗費大量線程資源
但是現在問題又來了,長連接配接的模式确實是不錯的,但是如果說每個裝置都要跟系統長期維持一個連接配接,那麼對于系統來說就需要搞一個線程,這個線程需要去維護一個裝置的長連接配接,然後通過這個連接配接跟一個裝置不停的通信,接收人家發送過來的請求,傳回響應給人家。
大家看下面的圖,每個裝置都要跟系統維持一個連接配接,那麼對于每個裝置的連接配接,系統都會有一個獨立的線程來維護這個連接配接。
因為你必須要有一個線程不停的嘗試從網絡連接配接中讀取請求,接着要處理請求,最後還要傳回響應給裝置。
那麼這種模式有什麼缺點呢?
缺點是很顯而易見的,假如說此時你有上百萬個裝置要跟你的系統進行連接配接,假設你的系統做了叢集部署一共有100個服務執行個體,難道每個服務執行個體要維持1萬個連接配接支撐跟1萬個裝置的通信?
如果這樣的話,每個服務執行個體不就是要維持1萬個線程來維持1萬個連接配接了嗎?大家覺得這個事兒靠譜嗎?
根據線上的生産經驗,一般4核8G的标準服務用的虛拟機,自己開辟的工作線程在一兩百個就會讓CPU負載很高了,最佳的建議就是在幾十個工作線程就差不多。
是以要是期望每個服務執行個體來維持上萬個線程,那幾乎是不可能的,是以這種模式最大的問題就在于這裡,沒法支撐大量連接配接。
4、Kafka遇到的問題:應對大量用戶端連接配接
實際上,對于大名鼎鼎的消息系統Kafka來說,他也是會面對同樣的問題,因為他需要應對大量的用戶端連接配接。
有很多生産者和消費者都要跟Kafka建立類似上面的長連接配接,然後基于一個連接配接,一直不停的通信。
舉個例子,比如生産者需要通過一個連接配接,不停的發送資料給Kafka。然後Kafka也要通過這個連接配接不停的傳回響應給生産者。
消費者也需要通過一個連接配接不停的從Kafka擷取資料,Kafka需要通過這個連接配接不停的傳回資料給消費者。
大家看下面的圖,感受一下Kafka的生産現場。
那假如Kafka就簡單的按照這個架構來處理,如果你的公司裡有幾萬幾十萬個的生産者或者消費者的服務執行個體,難道Kafka叢集就要為了幾萬幾十萬個連接配接來維護這麼多的線程嗎?
同樣,這是不現實的,因為線程是昂貴的資源,不可能在叢集裡使用那麼多的線程。
5、Kafka的架構實踐:Reactor多路複用
針對這個問題,大名鼎鼎的Kafka采用的架構政策是Reactor多路複用模型。
簡單來說,就是搞一個acceptor線程,基于底層作業系統的支援,實作連接配接請求監聽。
如果有某個裝置發送了建立連接配接的請求過來,那麼那個線程就把這個建立好的連接配接交給processor線程。
每個processor線程會被配置設定N多個連接配接,一個線程就可以負責維持N多個連接配接,他同樣會基于底層作業系統的支援監聽N多連接配接的請求。
如果某個連接配接發送了請求過來,那麼這個processor線程就會把請求放到一個請求隊列裡去。
接着背景有一個線程池,這個線程池裡有工作線程,會從請求隊列裡擷取請求,處理請求,接着将請求對應的響應放到每個processor線程對應的一個響應隊列裡去。
最後,processor線程會把自己的響應隊列裡的響應發送回給用戶端。
說了這麼多,還是來一張圖,大家看下面的圖,就可以了解上述整個過程了。
6、優化後的架構是如何支撐大量連接配接的?
那麼上面優化後的那套架構,是如何支撐大量連接配接的呢?
其實很簡單。這裡最關鍵的一個因素,就是processor線程是一個人維持N個線程,基于底層作業系統的特殊機制的支援,一個人可以監聽N個連接配接的請求。
這是極為關鍵的一個步驟,就僅此一個步驟就可以讓一個線程支援多個連接配接了,不需要一個連接配接一個線程來支援。
而且那個processor線程僅僅是接收請求和發送響應,所有的請求都會入隊列排隊,交給背景線程池來處理。
比如說按照100萬連接配接來計算,如果有100台機器來處理,按照老的模式,每台機器需要維持1萬個線程來處理1萬個連接配接。
但是如果按照這種多路複用的模式,可能就比如10個processor + 40個線程的線程池,一共50個線程就可以上萬連接配接。
在這種模式下,每台機器有限的線程數量可以抗住大量的連接配接。
是以實際上我們在設計這種支撐大量連接配接的系統的時候,完全可以參考這種架構,設計成多路複用的模式,用幾十個線程處理成千上萬個連接配接,最終實作百萬連接配接的處理架構。
------------- END -------------
另外推薦儒猿課堂的1元系列課程給您,歡迎加入一起學習~
網際網路Java工程師面試突擊課(1元專享)
SpringCloudAlibaba零基礎入門到項目實戰(1元專享)
億級流量下的電商詳情頁系統實戰項目(1元專享)
Kafka消息中間件核心源碼精講(1元專享)
12個實戰案例帶你玩轉Java并發程式設計(1元專享)
Elasticsearch零基礎入門到精通(1元專享)
基于Java手寫分布式中間件系統實戰(1元專享)
基于ShardingSphere的分庫分表實戰課(1元專享)