如在
有一天,我醒來時收到一封不滿的電子郵件,因為我們計劃在不久的將來推出 Alvin,原因是長時間拖延。 具體來說,客戶的 99% 延遲時間在 50 毫秒左右,遠高於我們的延遲預算。 這是令人驚訝的,因為我對該服務進行了廣泛的測試,特別是在延遲方面,這是一個常見的抱怨。
在將 Alvin 投入測試之前,我以每秒 40k 查詢 (QPS) 的速度進行了大量實驗,所有結果都顯示延遲小於 10 毫秒。 我準備好聲明我不同意他們的結果。 但再看一遍這封信,我發現了一些新的東西:我沒有準確測試他們提到的條件,他們的 QPS 比我低得多。 我測試的 QPS 為 40k,但他們只有 1k。 我又進行了一次實驗,這次 QPS 較低,只是為了安撫他們。
由於我在部落格中討論了這一點,您可能已經發現他們的數字是正確的。 我一遍又一遍地測試我的虛擬客戶端,結果都是一樣:請求數量少不僅會增加延遲,而且會增加延遲超過 10 毫秒的請求數量。 換句話說,如果在 40k QPS 時每秒大約有 50 個請求超過 50 毫秒,那麼在 1k QPS 時每秒有 100 個請求超過 50 毫秒。 悖論!
縮小搜尋範圍
當在具有許多組件的分散式系統中面臨延遲問題時,第一步是建立一個簡短的嫌疑犯清單。 讓我們更深入地研究一下 Alvin 的架構:
一個好的起點是已完成的 I/O 轉換清單(網路呼叫/磁碟查找等)。 讓我們試著找出延遲在哪裡。 除了與客戶端進行明顯的 I/O 之外,Alvin 還採取了額外的步驟:存取資料儲存。 然而,該儲存與 Alvin 在同一叢集中運行,因此那裡的延遲應該小於客戶端的延遲。 那麼,嫌疑犯名單如下:
- 從客戶端到 Alvin 的網路呼叫。
- 從 Alvin 到資料儲存的網路呼叫。
- 在資料儲存中的磁碟上搜尋。
- 從資料倉儲到 Alvin 的網路呼叫。
- Alvin 到客戶端的網路呼叫。
讓我們試著劃掉一些要點。
資料儲存與此無關
我做的第一件事是將 Alvin 轉換為不處理請求的 ping-ping 伺服器。 當它收到請求時,它會傳回一個空響應。 如果延遲減少,那麼 Alvin 或資料倉儲實作中的錯誤並不是聞所未聞的。 在第一個實驗中,我們得到下圖:
正如您所看到的,使用 ping-ping 伺服器時沒有任何改進。 這意味著資料倉儲不會增加延遲,而嫌疑犯清單減少了一半:
- 從客戶端到 Alvin 的網路呼叫。
- Alvin 到客戶端的網路呼叫。
偉大的! 該名單正在迅速縮減。 我想我已經差不多明白原因了。
遠程過程調用
現在是時候向您介紹一位新玩家了: gRPC
優化良好且廣泛使用,這是我第一次在這種規模的系統上使用它,我預計我的實現至少可以說是次優的。
可用性 gRPC
在堆疊中產生了一個新問題:也許是我的實作或我自己 gRPC
造成延遲問題? 將新嫌疑人加入名單:
- 顧客致電圖書館
gRPC
- 文庫
gRPC
對客戶端上的庫進行網路調用gRPC
在服務器上 - 文庫
gRPC
聯絡Alvin(乒乓伺服器情況下無操作)
為了讓您了解程式碼的樣子,我的客戶端/Alvin 實作與客戶端-伺服器實作沒有太大區別
注意:上面的列表有點簡化,因為
gRPC
可以使用您自己的(模板?)線程模型,其中執行堆疊是交織在一起的gRPC
和用戶實施。 為了簡單起見,我們將堅持使用這個模型。
分析將解決一切問題
劃掉資料儲存後,我以為我快完成了:「現在很簡單! 讓我們應用該配置文件並找出延遲發生的位置。” 我
我在客戶端和伺服器端獲取了四個設定檔:具有高 QPS(低延遲)和具有低 QPS(高延遲)的乒乓伺服器。 為了以防萬一,我還取得了一個範例處理器設定檔。 在比較配置檔案時,我通常會尋找異常的呼叫堆疊。 例如,在高延遲的壞方面,會有更多的上下文切換(10 次或更多)。 但就我而言,上下文切換的次數幾乎相同。 令我恐懼的是,那裡沒有任何重要的東西。
額外的調試
我很絕望。 我不知道我還可以使用哪些其他工具,我的下一個計劃本質上是用不同的變化重複實驗,而不是清楚地診斷問題。
如果什麼
從一開始,我就擔心具體的 50ms 延遲。 這是一個非常重要的時刻。 我決定從程式碼中刪除一些區塊,直到我能夠準確地找出導致此錯誤的部分。 然後進行了一項有效的實驗。
和往常一樣,事後看來,一切都是顯而易見的。 我將客戶端放置在與 Alvin 相同的電腦上 - 並向 localhost
。 而延遲的增加消失了!
網路出現問題。
學習網路工程師技能
我必須承認:我對網路技術的了解很糟糕,尤其是考慮到我每天都與它們一起工作。 但網路是主要嫌疑人,我需要學習如何調試它。
幸運的是,網路喜愛那些想要學習的人。 ping 和tracert 的組合似乎是調試網路傳輸問題的一個足夠好的開始。
首先,我推出了
然後我嘗試了
因此,導致延遲的不是我的程式碼、gRPC 實作或網路。 我開始擔心我永遠無法理解這一點。
現在我們使用什麼作業系統
gRPC
在 Linux 上廣泛使用,但在 Windows 上卻很奇特。 我決定嘗試一個實驗,結果很有效:我創建了一個 Linux 虛擬機,為 Linux 編譯了 Alvin,然後部署了它。
發生的事情是這樣的:儘管資料來源沒有什麼不同,但 Linux 乒乓球伺服器沒有與類似的 Windows 主機相同的延遲。 事實證明,問題出在 Windows 的 gRPC 實作。
內格爾演算法
一直以來我都以為我丟了一面旗幟 gRPC
。 現在我明白它到底是什麼了 gRPC
Windows 標誌遺失。 我發現了一個內部 RPC 庫,我相信它可以很好地適用於所有標誌集
幾乎 完成:我開始一次刪除一個新增的標誌,直到回歸返回,以便我可以找出原因。 這是臭名昭著的
gRPC
該標誌是在 TCP 套接字的 Linux 實作中設定的,但在 Windows 中沒有設定。 我是這個
結論
低QPS下的較高延遲是由作業系統優化引起的。 回想起來,分析並沒有偵測到延遲,因為它是在核心模式下完成的,而不是在
至於 localhost 實驗,它可能沒有觸及實際的網路程式碼,而且 Nagle 的演算法沒有運行,因此當客戶端透過 localhost 到達 Alvin 時,延遲問題就消失了。
下次當您看到延遲隨著每秒請求數的減少而增加時,Nagle 的演算法應該會出現在您的嫌疑犯名單上!
來源: www.habr.com