當前位置:
首頁 > 知識 > 程序員,豈能被網站吞吐量難住?

程序員,豈能被網站吞吐量難住?

程序員,豈能被網站吞吐量難住?

打開今日頭條,查看更多圖片

作者 | 菜菜

責編 | 郭芮

本文系作者投稿,版權歸作者所有


YY妹:菜菜哥,有個事你還得幫我(苦笑一下).....前幾天寫了幾個介面,領導讓提高一下介面吞吐量。

菜菜:這是你技術提高的大好機會呀!

YY妹:可吞吐量具體是什麼?怎麼提高呢?

菜菜:來,哥給你解釋一番。

什麼是吞吐量?

吞吐量是指對網路、設備、埠、虛電路或其他設施,單位時間內成功地傳送數據的數量(以比特、位元組、分組等測量)。

以上的定義比較寬泛,定義到網站或者介面的吞吐量是這樣的:吞吐量是指系統在單位時間內處理請求的數量。這裡有一個注意點就是單位時間內,對於網站的吞吐量這個單位時間一般定義為1秒,也就是說網站在一秒之內能處理多少HTTP(HTTPS/TCP)請求。與吞吐量對應的衡量網站性能的還有響應時間、並發數、QPS每秒查詢率。

  • 響應時間是一個系統最重要的指標之一,它的數值大小直接反應了系統的快慢。響應時間是指執行一個請求從開始到最後收到響應數據所花費的總體時間。
  • 並發數是指系統同時能處理的請求數量,這個也是反應了系統的負載能力。
  • 每秒查詢率(QPS)是對一個特定的查詢伺服器在規定時間內所處理流量多少的衡量標準,在網際網路上,作為域名系統伺服器的機器的性能經常用每秒查詢率來衡量。對應fetches/sec,即每秒的響應請求數,也即是最大吞吐能力。

我們以高速收費站為例子也許更直觀一些,吞吐量就是一天之內通過的車輛數,響應時間就是車速,並發數就是高速上同時奔跑的汽車數。由此可見其實以上幾個指標是有內在聯繫的。比如:響應時間縮短,在一定程度上可以提高吞吐量。

其實以上幾個指標主要反映了兩個概念:

  • 系統在單位時間之內能做多少事情;
  • 系統做一件事情需要的時間。

提高吞吐量

以下場景都是在假設程序不發生異常的情況下。

伺服器(進程)級別

伺服器級別增加網站吞吐量也是諸多措施中最容易並且是效果最好的,如果一個網站能通過增加少量的伺服器來提高吞吐量,應該優先採用。

畢竟一台伺服器的費用相比較一個程序員費用來說要低的多。但是有一個前提,就是你的伺服器是系統的瓶頸,網站系統之後的其他系統並非瓶頸。

如果你的系統的瓶頸在DB或者其他服務,盲目的增加伺服器並不能解決你的問題。

通過增加伺服器來解決你的網站瓶頸,意味著你的網站需要做負載均衡,如果沒有運維相關人員,你可能還得需要研究負載均衡的方案,比如LVS、Nginx、F5等。

我曾經面試過很多入道不久的同學,就提高吞吐量問題,如果沒有回答上用負載均衡方案的基本都PASS了。

不要說別的,這個方案就是一個基礎,就好比學習一個語言,你連最基本的語法都不會,我憑什麼讓你通過?

其實現在很多靜態文件採用CDN,本質上也可以認為是增加伺服器的策略。

線程級別

當一個請求到達伺服器並且正確的被伺服器接收之後,最終執行這個請求的載體是一個線程。

當一個線程被CPU載入執行其指令的時候,在同步的狀態下,當前線程會阻塞在那裡等待CPU結果,如果CPU執行的是比較慢的IO操作,線程會一直被阻塞閑置很長時間,這裡的很長是對比CPU的速度而言。

當一個新的請求到來的時候,如果沒有新的線程去領取這個任務並執行,要麼會發生異常,要麼創建新的線程。

線程是一種很稀缺的資源,不可能無限制的創建。這種情況下我們就要把線程這種資源充分利用起來,不要讓線程停下來。這也是程序推薦採用非同步的原因。

試想,一個線程不停的在工作,遇到比較慢的IO不會去等待結果,而是接著處理下一個請求,當IO的結果返回來得到通知的時候,線程再去取IO結果,豈不是能在相同時間內處理更多的請求。

程序非同步化(非阻塞)會明顯提高系統的吞吐量,但是響應時間可能會稍微變大。

還有一點,盡量減少線程上下文在CPU的切換,因為線程上線文切換的成本也是比較大的,在線程切換的時候,CPU需要把當前線程的上下文信息記錄下來用以下次調用的時候使用,然後把新線程的上下文信息載入然後執行。這個過程相對於CPU的執行速度而言,要慢很多。

不要拿Golang反駁以上觀點,Golang的協程雖然是用戶級別比線程更小的載體,但是最終和CPU進行交互的還是線程。

CPU級別

在講CPU級別之前,如果有一定的網路模型的基礎,也許會好一些。這裡大體闡述一下,現代操作系統都採用虛擬定址的方式,它的定址空間(虛擬存儲空間)為4G(2的32次方)。操作系統將虛擬空間分為兩類:內核空間和用戶空間。

內核空間獨立於用戶空間,有訪問受保護的內存空間、IO設備的許可權(所有的用戶空間共享)。

用戶空間就是我們的應用程序運行的空間,其實用戶空間並沒有操作各種IO設備的許可權,像我們平時讀取一個文件,本質上是委託內核空間去執行讀取指令的,內核空間讀取到數據之後再把數據複製到程序運行的空間,最後應用程序再把數據返回調用方。

程序員,豈能被網站吞吐量難住?

通過上圖大體可以看出,內核會為每個I/O設備維護一個buffer(同一個文件描述符讀和寫的buffer不同),應用程序發出一個IO操作的指令其實通過了內核空間和用戶空間兩個部分,並且發生了數據的複製操作。這個過程其實主要包含兩個步驟:

  • 用戶進程發出操作指令並等待數據;
  • 內核把數據返回給用戶進程(buffer的複製操作)。

根據這兩個操作的不同表現,所以IO模型有了同步阻塞,同步非阻塞,非同步阻塞,非同步非阻塞的概念,但是這裡並非此文的重點,所以不在展開詳細介紹。

利用CPU提高系統吞吐量主要目標是提高單位時間內CPU運行的指令數,避免CPU做一些無用功:

  • cpu負責把buffer的數據copy到應用程序空間,應用程序再把數據返回給調用方,假如這個過程發生的是一次Socket操作,應用程序在得到IO返回數據之後,還需要網卡把數據返回給client端,這個過程又需要把剛剛得到的buffer數據再次通過內核發送至網卡,通過網路傳送出去。由此可見cpu把buffer數據copy到應用程序空間這個過程完全沒有必要,在內核空間完全可以把buffer數據直接傳輸至網卡,這也是零拷貝技術要解決的問題。具體的零拷貝技術在這裡不再展開。
  • 不要讓任何設備停下來,不要讓任何設備做無用功。
  • 通過增加cpu的個數來增加吞吐量。

網路傳輸級別

至於網路傳輸級別,由於協議大部分是TCP/IP,所以在協議傳輸方面優化的手段比較少,但是應用程序級別協議可以選擇壓縮率更好的,比如採用grpc會比單純的HTTP協議要好很多,HTTP2 要比HTTP 1.1要好很多。

另外一方面網卡盡量加大傳輸速率,比如千兆網卡要比百兆網卡速度更快。由於網路傳輸比較偏底層,所以人工干預的切入點會少很多。

最後總結

大部分程序員都是工作在應用層,針對應用級別代碼能提高吞吐量的建議:

  • 加大應用的進程數,增加並發數,特別在進程數是瓶頸的情況下;
  • 優化線程調用,盡量池化;
  • 應用的代碼非同步化,特別是非同步非阻塞式編程對於提高吞吐量效果特別明顯;
  • 充分利用多核CPU優勢,實現並行編程;
  • 減少每個調用的響應時間,縮短調用鏈,例如通過加索引的方式來減少訪問一次資料庫的時間。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 CSDN 的精彩文章:

Google 擊敗蘋果!| 極客頭條

TAG:CSDN |