網站連接超時(時延敏感業務低概率超時問題分析)

前言作為阿裡雲底層提供的基礎設施,內部的物理網絡和許多網絡產品在數據平面給客戶的可操作性並不高,從一定程度上來說是個黑盒。當然,在傳統的IDC環境,業務和物理網絡之間也存在同樣的隔閡。所以在遇到業務卡頓、延遲、不通等問題的時候,很容易懷疑到網絡。因此如何抽絲撥繭,找到正確的方向對癥下藥才能夠真正的解決問題。畢竟“真相隻有一個”。在進行問題排查和處理的時候,難度最高的場景就是極度偶發,復現頻率極低的問題。尤其在網絡排查的領域,通常為瞭性能和控制資源消耗,不會將每一個數據包的情況都一一記錄下來,對於一次偶發的應用層記錄的超時,網絡層通常沒有明確的對應此次應用層調用的包交互記錄,因此排查起來非常困難。在這次的案例中,我們通過一個客戶端查詢redis集群偶發超時的小案例,來說明一些診斷思路、排查手段,進而引出一些在網絡方面提高業務穩定性的最佳實踐。問題環境這次的問題是一個交互性web應用中的一個子模塊,主要進行redis查詢,可以簡單將其理解為視頻彈幕網站中“查詢彈幕”的小模塊。這個模塊的拓撲非常簡單:在上面的拓撲中,客戶使用ECS構建瞭一個Redis集群,前面用Codis實現瞭一層Redis Proxy (為瞭通用性,後面均用Redis proxy來描述),並將這組Redis proxy掛載在一個SLB後,通過SLB的單一入口提供服務。問題現象客戶的主要問題是訪問其自建Redis系統的客戶端會不定期出現超時報錯,盡管總體概率不高,但是報錯概率高於其業務運行在原有機房的水平。超時報錯主要有兩種情況:一般情況下超時數量與業務量呈正相關,非業務高峰期但是SLB、ECS的資源使用率均較低。會存在突發性的大量超時。診斷思路作為問題排查的第一步,首先要瞭解到問題本身所處的上下文和環境。在平時診斷問題收集信息的時候,為瞭有條理的、全面的收集信息,筆者將需要收集的信息分為兩種類型:資源因素和環境因素。資源因素:即發生問題的系統的拓撲。比如涉及的各種應用程序、主機、轉發設備、鏈路資源等,並且要充分理解這些資源組建在拓撲中起到的作用。環境因素:即描述這個問題所需要的信息,比如報錯日志,問題發生時間、頻率,應用層設置的超時時間等等。瞭解資源因素和環境因素後,可以將問題的定義明確為:在哪些資源上發生瞭什麼樣的問題,然後根據該定義收集與問題相關的信息,並在解讀和分析的時候通過數據排除所有的不可能,這樣才能進行高效和準確的問題排查。在本案例中,資源因素已經在上文的拓撲中闡述,問題所涉及的環境因素包括:客戶設置的是50ms超時,在客戶端的報錯是read timeout(代表排除瞭tcp的三次握手超時),報錯頻率為非業務高峰期一個小時10個左右,業務高峰期1小時上百個。但是偶爾(一周內偶爾發生一次到兩次)無論業務高峰還是非業務高峰都會有較多的,上百次的read timeout和connect timeout。客戶已經排查過redis,其查詢時間每次耗時不超過10ms,而redis proxy沒有記錄轉發的日志。排查方法因為所有可用的日志僅能定位到這個系統的兩端(客戶端、Redis),需要收集進一步的信息。面對這種超時類的問題,最直接、有效的辦法就是進行抓包。而該問題發生的頻率不高,整個系統流量也比較大,一直開著抓包很容易將磁盤撐滿,因此需要使用循環抓包:tcpdump -i <接口|any> -C <每文件大小> -W <文件個數> -w <保存文件名> 抓包過濾條件
該命令的意思是針對某個接口,按照過濾條件進行抓包,保存指定文件名前綴的文件下,最多占用每文件大小*文件個數 的磁盤空間並循環覆蓋。開啟循環抓包後,等待客戶端報錯再次出現,即可抓到現場的包交互過程。抓包的結果文件可以使用wireshark打開,但是使用循環抓包抓到的數據包文件較大、數量較多,可以使用下面的小技巧進行快速的過濾://在安裝瞭wireshark的電腦上都會有capinfos和tshark兩個命令,以筆者使用的macOS為例
~$ capinfos -a -e *cap //使用capinfos查看抓包文件的其實時間和結束時間,選取包含報錯時間+-超時時間的文件,其他文件就不需要瞭
File name: colasoft_packets.cap
Packet size limit: inferred: 66 bytes – 1518 bytes (range)
First packet time: 2019-06-12 09:00:00.005519934
Last packet time: 2019-06-12 09:59:59.998942048
File name: colasoft_packets1.cap
Packet size limit: inferred: 60 bytes – 1518 bytes (range)
First packet time: 2019-06-12 09:00:00.003709451
Last packet time: 2019-06-12 09:59:59.983532957
//如果依然有較多文件,則可以使用tshark命令進行篩選。比如報錯中提到Redis查詢一個key超時,則可以用以下腳本找到這次查詢請求具體在哪個文件中:
~$ for f in ./*; do echo $f; tshark -r $f ‘tcp.payload contains “keyname”‘; done
找到對應的請求之後,再用wireshark打開該文件,找到對應數據包,跟蹤對應流來找到五元組和整個流的上下文交互。在本案例中,通過對比客戶端、redis proxy和redis 三層的抓包,發現客戶端發出請求到收到響應的時間的確在問題發生時話費瞭100多ms,而這部分耗時主要發生在Redis將響應返回給Redis proxy的丟包重傳導致。整體時序示意圖如下:對於從抓包中觀察到的丟包現象,在通過阿裡雲內部監控確定瞭物理鏈路的確不存在丟包的情況下,我們發現Redis proxy所在的ECS上,虛擬化層面的後端驅動在向前端驅動送包的時候,前後端隊列的丟包計數的增長趨勢和業務超時的頻率有相同趨勢,進一步排查發現客戶ECS操作系統內的網卡多隊列沒有開啟,導致隻有一個CPU處理網卡中斷,而當流量有瞬間突增的時候,CPU來不及處理網卡中斷導致前後端隊列堆積,隊列溢出後導致丟包。為瞭解決這個問題,我們建議客戶將網卡多隊列開啟,並將不同網卡隊列中斷的CPU親和性綁定在不同的CPU上。對於阿裡雲ECS,可以使用的網卡隊列是和實例規格綁定的,具體可以參考ECS實例規格文檔。簡單的開啟網卡隊列並使用irqbalance 自動調度網卡隊列中斷CPU親和性的方法可以參考阿裡雲官方文檔。本案例中客戶開啟網卡多隊列並開啟irqbalance服務之後,每小時都出現的訪問超時問題已經解決,但是還是會有每隔幾天會出現的突發性大量超時。經過匯聚客戶的報錯信息和阿裡雲底層的網絡監控,我們最終確認這種每隔幾天就會出現的突發性大量超時是因為阿裡雲底層的跨可用區間鏈路抖動導致的。阿裡雲的每一個可用區可以理解為是一個機房,而不同可用區之間可以互為同城災備關系。為瞭確保可用區之間不會故障擴散,不同可用區機房需要保持一定物理機距離,並通過同城傳輸光纜將所有可用區相互連接實現可用區之間的互訪。連接可用區之間的同城傳輸光纜的可靠性遠低於機房內部跳纖,且經常容易受到道路施工、質量劣化的影響,導致鏈路中斷。為瞭保證業務連續性,阿裡雲提供瞭充足的冗餘鏈路並使用傳輸倒換、路由切換等技術確保部分跨可用區鏈路時故障可以自動收斂,但是在倒換過程中產生的丟包卻無法完全避免。根據阿裡雲底層監控,當一條跨可用區鏈路中斷時,通常會導致持續3-5秒的1%左右的丟包(具體需要看中斷鏈路數量占總鏈路數量的占比),而反映在業務上,則有可能造成時延敏感業務接近1分鐘的部分超時報錯。因此在本案例中造成瞭突增的超時報錯。假如客戶使用資源時,可用區分佈非常散亂,則會造成可用區間鏈路抖動對業務影響的頻率升高。比如客戶的客戶端ECS分佈在多個可用區(A、B),SLB在可用區C ,Redis proxy和Redis在可用區D、E,則A到C、B到C、C到D、D到E的跨可用區鏈路抖動都會影響到整個系統。最佳實踐通過這個案例我們可以總結出關於主機網絡和網絡部署方面兩個最佳實踐:主機網絡方面:打開網卡多隊列並將網卡軟中斷打散以獲取最佳的網絡性能。總體來講,為瞭獲得穩定的網絡性能,有以下通用建議:使用VPC實例:除瞭網絡租戶隔離、支持專線、VPN網關等好處外,VPC環境在底層轉發能力上也比經典網絡實例有大幅提高,最新一代實例均基於VPC環境實現,因此也提供瞭更強的網絡轉發性能。使用獨享型實例:獨享型實例采用嚴格的資源隔離技術,確保虛擬機不會收到“吵鬧的鄰居”影響。打開網卡多隊列並綁定網卡軟中斷處理CPU親和性:對於不同網卡隊列使用不同CPU進行處理,提高網絡處理性能將網卡多個隊列分別綁定到某幾個專用CPU上,而其他進程綁定到其他CPU上,讓網卡軟中斷處理使用專門的CPU:適用於純轉發類、對網絡性能要求極高的服務。//綁定網卡軟中斷的方法:
//1. 首先看cat /proc/interrupts | grep virtio,在阿裡雲提供的標準操作系統中,virtio0是網卡隊列
~$cat /proc/interrupts | grep virtio
//omit outputs
31: 310437168 0 0 0 PCI-MSI-edge virtio0-input.0
32: 346644209 0 0 0 PCI-MSI-edge virtio0-output.0
//將第一列的中斷號記錄下來,修改下面的文件綁定CPU親和性
echo <cpu affinity mask> /proc/irq/{irq number}/smp_affinity
//具體CPU affinity mask可以參考manpage https://linux.die.net/man/1/taskset,這裡不再說明。
物理網絡方面:建議從業務容忍度和時延敏感度進行權衡來選擇業務的部署。從業務容忍度的角度來說,如果tcp協議中發生瞭丟包,那麼最壞情況下需要等待RTO超時才能夠重傳(tail drop場景,其他場景有fast retrans機制),而RTO超時的最小取值在kernel中的定義為200HZ,即200ms。對於內網互訪或者同城互訪這種時延較低的場景,可以理解為一次丟包的最壞情況就是200ms的重傳,因此對於關鍵業務,至少將請求超時設置在200ms以上,讓tcp有一次重傳的機會。而對於非關鍵業務,一次查詢是否返回數據並不關鍵的,則可以將請求超時設置的更小以便保護整個系統。因此業務容忍有兩個方面:業務可以容忍錯誤,或者業務可以容忍重傳。從時延敏感度的角度來說,為瞭確保時延敏感業務盡量少的受跨可用區鏈路影響,建議盡量將時延敏感業務的整個業務調用都在一個可用區內完成。而不同的可用區之間盡管提供相同服務,但是之間不會經常跨可用區調用。比如web server層調用提供緩存服務的Redis在本可用區完成,隻有緩存沒有命中的少量情況,才有可能跨可用區查詢數據庫,甚至使用隻讀實例等其他技術,將跨可用區鏈路抖動的影響降至最低。結束語通過上面的案例和最佳實踐的說明,可以看到“權衡”在業務系統架構涉及和部署當中是無處不在的。所謂優化就是在給定的環境下,為瞭實現業務目標,將資源傾斜到最需要的地方。另一方面,對於許多客戶在上雲前的系統架構中,受限與機房成本、位置等原因,可能沒有使用過多機房的組網場景,而雲計算對這些客戶帶來的除瞭基礎設施跨代升級的便利之外,還提供瞭天然的容災能力,而業務系統的架構和部署也需要增加因容災所帶來的組網場景的復雜化。

本文出自快速备案,转载时请注明出处及相应链接。

本文永久链接: https://kuaisubeian.cc/48981.html

kuaisubeian