聊聊介面最大併發處理數

ITPUB社群發表於2023-11-21

來源:waynblog

今天跟大家聊聊一個 Java 界的老話題,就是怎麼理解介面的最大併發處理數。

前言

生活在 2023 年的網際網路時代下,又是在國內網際網路越發內卷的背景下,相信大家面試找工作、網上學習查資料時都瞭解過網際網路系統設計三高指標,那就是高併發、高效能、高可用。本文主要講高併發、高效能相關。本質上高效能也是為了給高併發鋪平道路。而高併發設計中一部分就是對應了本文主題介面最大併發數。本文思維導圖如下,

聊聊介面最大併發處理數

併發和並行

再開始講併發之前,我需要再給大家回顧一些舊知識。

什麼是併發?什麼是並行...

併發(Concurrency)

早期計算機的 CPU 都是單核的,一個 CPU 在同一時間只能執行一個程式/執行緒,當系統中有多個程式/執行緒等待執行時,CPU 只能執行完一個再執行下一個。

計算機在執行過程中,有很多指令會涉及 I/O 操作,而 I/O 操作又是相當耗時的,速度遠遠低於 CPU,這導致 CPU 經常處於空閒狀態,只能等待 I/O 操作完成後才能繼續執行後面的指令。

為了提高 CPU 利用率,減少等待時間,人們提出了一種 CPU 併發工作的理論。

所謂併發,就是透過一種演算法將 CPU 資源合理地分配給多個任務,當一個任務執行 I/O 操作時,CPU 可以轉而執行其它的任務,等到 I/O 操作完成以後,或者新的任務遇到 I/O 操作時,CPU 再回到原來的任務繼續執行。

下圖展示了兩個任務併發執行的過程:

聊聊介面最大併發處理數

雖然 CPU 在同一時刻只能執行一個任務,但是透過將 CPU 的使用權在恰當的時機分配給不同的任務,使得多個任務在視覺上看起來是一起執行的。CPU 的執行速度極快,多工切換的時間也極短,使用者根本感受不到,所以併發執行看起來才跟真的一樣。

並行(Parallelism)

併發是針對單核 CPU 提出的,而並行則是針對多核 CPU 提出的。和單核 CPU 不同,多核 CPU 真正實現了“同時執行多個任務”。

多核 CPU 內部整合了多個計算核心(Core),每個核心相當於一個簡單的 CPU,如果不計較細節,你可以認為給計算機安裝了多個獨立的 CPU。

多核 CPU 的每個核心都可以獨立地執行一個任務,而且多個核心之間不會相互干擾。在不同核心上執行的多個任務,是真正地同時執行,這種狀態就叫做並行。

例如,同樣是執行兩個任務,雙核 CPU 的工作狀態如下圖所示:

聊聊介面最大併發處理數

雙核 CPU 執行兩個任務時,每個核心各自執行一個任務,和單核 CPU 在兩個任務之間不斷切換相比,它的執行效率更高。

思考一下

那麼這裡我們講了關於併發、並行概念與我們的介面最大併發處理數之間有什麼關係嘞?放心這都是鋪墊,為了讓你好消化後面的內容。

這裡我給大家總結下併發與並行的概念:

  • 併發:在同一時間段內,多個任務都在執行,但不一定是同時執行。這意味著這些任務在輪流使用 CPU 的時間片,給人一種它們在“同時”執行的錯覺。併發的真正含義在於,儘管多個程式或程式可能正在執行,但每次只有一個程式或執行緒實際上正在使用 CPU。
  • 並行:指在同一時刻,多個任務都在執行。這通常需要多個處理器或多核的 CPU 來實現,因為只有這樣,每個處理器或核心才能在同一時刻執行一個任務。例如,當音樂軟體和 IDEA 同時執行時,如果計算機有兩個以上的 CPU 核心,那麼這兩個應用程式就可以真正地並行執行。

大家注意我上面加粗的字型,併發強調的是在同一段時間內,它是一個時間範圍的概念。打個比方,併發是一個人同時吃三個饅頭,吃完一個饅頭需要 1 分鐘,他就算胃口在大,也只能一個一個饅頭吃,吃完三個需要花 3 分鐘。

再看並行,並行強調的在同一時刻。打個比方,並行就是三個人同時吃三個饅頭。這三個人可以在同一時刻一人吃一個饅頭。吃完三個只需要花 1 分鐘。

那麼看到這裡,我在問你個問題,3 個人的在 3 分鐘內最多能吃多少個饅頭?

相信大家都能告訴我。

理解介面的最大併發處理數

在 Java 語言裡面,我們怎麼理解併發跟並行嘞?還是跟吃饅頭一樣,我給大家打個比方,相信大家就明白了。

比如說我有一個介面,他的 RT (響應時長)是 50 毫秒,只有一個執行緒處理客戶端請求,那這個執行緒在 1000 毫秒就能夠處理 20 個客戶端請求。

這裡 20 就代表一個執行緒在 1 秒內的最大併發數。

那假如有兩個執行緒處理客戶端請求,介面的最大併發數是不是變成了 40,三個執行緒處理客戶端請求,介面的最大併發數就變成了 60,以此類推。

這裡我們就可以得出一個公式,執行緒個數 * 單執行緒最大併發數 就代表介面的最大並行處理數。

那麼根據公式,我們得出一個結論,透過增大執行緒數或者減少介面響應時間可以增大介面的最大併發處理數

聊聊 Tomcat 容器的併發處理配置

在 Spring Boot 釋出後,Tomcat 就成為了 Spring Boot 預設的 web 容器。這裡結合上文內容,給大家講解下 Spring Boot 中涉及 Tomcat 伺服器的一些關鍵引數,以及在高併發情況下如何透過這些引數來控制請求量。Spring boot 配置檔案如下,

SpringBoot 版本:3.1.5

server:
  port: 8080
  tomcat:
    threads:
      max: 200
      min-spare: 10
    accept-count: 100
    max-connections: 8192

server.port

該引數用於指定伺服器監聽的埠號。透過配置不同的埠號,可以實現多個服務在同一主機上並行執行。

這裡為了方便大家理解,我用開飯店來給大家做比喻。透過指定伺服器 ip + 啟動埠,就相當於告訴顧客我們的飯店位置,等待顧客上門吃飯。

server.tomcat.threads.max

該引數定義了 Tomcat 伺服器的最大執行緒數。在高併發情況下,可以透過增加最大執行緒數來提高伺服器最大併發處理數的能力,但需要注意伺服器的硬體資源限制。

threads.max 相當於設定飯店在最忙碌時候,需要的最大的服務員數量,假如說一個服務員只能服務 1 個客人,那麼 200 個服務員就可以同時服務 200 個客人,注意這是並行服務哦。

server.tomcat.threads.min-spare

此引數用於設定伺服器在空閒狀態下保持的最小執行緒數。確保伺服器在處理請求時有足夠的執行緒可用,以避免延遲。

threads.min-spare 相當於設定飯店空閒時候需要的最少的服務員數量。

server.tomcat.max-connections

該引數指定伺服器接受和處理的客戶端最大連線數。超過這個限制後,會放入 accept-count 佇列中

max-connections 相當於設定飯店空間內客人的最大容納數量,注意是容納,進了飯店的客人不是一進來就能享受服務的。往往還需要等待一段時間。這段時間就是當服務員服務上一個客人完畢後,有空出來的服務員才能給進店新客人服務。

server.tomcat.accept-count

此引數定義了當所有可能的請求處理執行緒都在使用時,傳入連線請求的最大佇列長度。在高併發情況下,可以透過適當調整此引數來控制連線請求的排隊長度。

accept-count 相當於設定飯店門口的排隊人數大小。想一想我們外出吃飯的時候,什麼情況需要排隊,當然是店內爆滿,沒有座位。那麼這個時候你就需要排個隊了。注意如果說排隊人都滿了,怎麼辦?


這個時候飯店就會通知沒有排上隊,還想要假如排隊的人,“你們不要排隊了,今天吃飯人滿了,大家去別處吃飯吧!”。


對應上 Tomcat 就是遇到客戶端連線數量超過了 max-connections + accept-count 大小後的情況,此時 Tomcat 會直接拒絕新的客戶端連線。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024420/viewspace-2996288/,如需轉載,請註明出處,否則將追究法律責任。

相關文章