深入解讀雲場景下的網絡抖動

一、網絡抖動背景

延時高,網絡卡,卡住了美好!

應用抖,業務驚,驚擾了誰的心?

當你在觀看世界盃梅西主罰點球突然視頻中斷了幾秒鐘

當你在遊戲中奮力廝殺突然手機在轉圈圈無法響應

當你守候多時爲了搶一張化妝品優惠券突然遲遲加載不出來...

我們經常在觀看視頻、手機遊戲、網上購物時,會遇到上面這些煩心事,作爲用戶,我們總有被卡在“臨門一腳”的感覺,此時的你,是否有種想把手機或電視砸掉的衝動?或者破口大罵網絡服務商的線路不穩定?是的,這種現象一般是網絡抖動引起的。

“高頻率、難攻克”一直是業界對抖動問題的評價,特別是在我們雲計算場景下,複雜的網絡拓撲,衆多的業務承載形態,容器、虛擬機和傳統的物理機並存,業務的應用也出現了微服務衆多、多語言開發、多通信協議的鮮明特徵,這給我們定位這類問題帶來非常大的挑戰。試想從我們的手機或者 PC 瀏覽器發出的一個付款請求,可能要經過你的家庭路由器,運營商網絡,雲服務商物理網絡、虛擬網絡,以及電商服務器,容器或者虛擬機,最後纔是具體的服務程序對請求進行處理,這裏面每個節點都可能存在延遲。

購物、遊戲、視頻、金融等領域,受限於傳統的 IDC 物理網絡的環境因素,多樣化的雲網絡場景,以及業務系統的複雜性,所有涉及到網絡請求和處理的地方,都會存在業務網絡抖動的情況。

在雲服務商內部,業務所在的 ECS 服務器,日誌的存儲和上傳、數據庫訪問,可能分散在不同的節點,節點之間也有各種網關和內部網絡。當出現抖動時,每個功能模塊都只能維護自己的節點診斷信息,無法通過統一平臺呈現具體時延信息,相互之間的自證清白的能力比較弱。

到具體業務和應用處理上,由於操作系統上面跑着各種任務,相互之間的調度和處理都會有干擾,內存分配、報文解析、IO 訪問延遲等等,都給我們分析抖動問題帶來困難。

二、網絡抖動的定義

2.1 網絡抖動的定義和現象

前面我們一直在提延遲,提抖動,以及抖動如何難分析。現在我們回到一個最初的問題,什麼是網絡延遲?什麼是網絡抖動?雲計算場景中抖動都有哪些具體的現象?

網絡延遲是指報文在網絡中傳輸所用的時間,即從報文開始進入網絡到它開始離開網絡所經歷的時間。各式各樣的數據在網絡介質中通過網絡協議(如 TCP/IP)進行傳輸,如果信息量過大不加以限制,超額的網絡流量就會導致設備反應緩慢,從而造成網絡延遲。

而抖動是 Qos 裏面常用的一個概念,當報文經過交換機、路由器等設備時,容易出現網絡擁塞,通常報文會進行排隊,這個排隊延遲將影響端到端的延遲,並導致通過同一個連接進行傳輸的報文經歷的延遲各不相同,所以抖動,就是用來描述這樣一延遲變化的程度。網絡抖動值越小說明網絡質量越穩定。舉例說明,假設 A 網絡最大延遲是 15 毫秒,最小延遲爲 5 毫秒,那麼網絡抖動值是 10 毫秒

總結起來,網絡抖動是指在某一時刻業務的流量下跌、正常業務指標受損,網絡出現延遲等。延時和抖動主要的後果是影響用戶體驗,特別是在遊戲場景中更是來不得半點抖。試想當你在打怪買裝備時抖了那麼 20ms,裝備沒了,此時捶胸頓足砸鍵盤也於事無補啊。

另外,雲場景下,用戶不僅關心正常場景的平均延遲,對異常場景下的長尾延遲,也越來越關注。影響長尾延遲的因素,如宕機、網絡延時、磁盤抖動、系統夯機等等。長尾延遲還存在着放大效應,比如系統 A 串行向系統 B 發送 5 個請求,前一個請求返回才能進行後一個請求,當系統 B 出現一個慢請求時,會堵住後面 4 個請求,系統 B 中的 1 個 Slow IO 可能會造成系統 A 的 5 個 Slow IO。所以,每個節點的每一個系統服務都有義務主動減少或降低處理延遲。

我們通常說的網絡抖動,拿雲計算場景來看,可能有如下現象:

1、兩臺 ECS 服務器之間從發出 ping request 到 reply 回覆的正常水平是 5ms,在某個時間點突然發生抖動,增加至 50ms,隨後馬上恢復。

2、負載均衡 SLB 上的 HTTP 請求平均延遲的正常水平在 10ms,在某個時間點突然發生抖動,整體延遲增加至 100ms,隨後馬上恢復。

3、通過 ECS 訪問 RDS 數據庫,在某個時間點突然打印大量日誌

如"SocketTimeOut"、"Request timeout" 等,持續時間爲秒級,隨後馬上恢復。

從上述現象可以看出,網絡抖動在雲計算場景下有了新的理解,它產生的原因可能是由於發送端和接收端之間的鏈路、系統內部的一個瞬時抖動,比如業務所在 Linux 系統 crash、鏈路有丟包重傳、網卡 up/down、交換機緩存瞬時打滿等。

我們先看一下解決網絡延遲和抖動的一般方法:

1、交換機和路由器等設備,主動避免網絡報文排隊和處理時間。

2、雲網絡及上雲等網關設備主動降低處理延遲,通過硬件提高轉發速度,通過 RDMA 技術降低時延。

3、業務應用所在的虛擬機或者容器的內核協議棧打開 tso 等硬件加速方案,採用零拷貝等技術降低延遲。

2.2 網絡抖動的分類

在雲計算場景下,通過對抖動問題進行分析,根據抖動發生的時刻和是否可復現,將抖動分成三大類:

1、當前還在發生的抖動問題,且這個現象還繼續存在,我們稱之爲 Current 當前抖動。這類問題一般由於鏈路中有持續性或週期性丟包、Qos 限流引起。

2、過去某一時刻出現的抖動,當前現象已不存在,我們稱之爲歷史抖動。這類抖動問題一般在日誌中打印“socket timeout”,或者有重傳報文記錄,這類問題相對來說少,很難定位。

3、通過 ping 包去檢測連通性或網絡狀態,經常有幾十甚至上百 ms 的延遲,而正常情況是幾個 ms 不到。ping 毛刺問題,有可能該現象還一直存在,或者是間歇性地出現。這類問題一般是業務負載高(load 高),系統卡頓,或者存在虛擬化環境中的 CPU 爭搶問題。

一般的,丟包和重傳會引起當前和歷史抖動問題,拿 tcp 協議來說,只要從 tcp 發出去的報文在鏈路上出現了丟包,內核協議棧就會對該報文進行重傳,大量的重傳會導致業務超時和引起網絡抖動。因此,丟包問題,也是網絡抖動的頭號宿敵。但還得明確一個概念:網絡丟包可能造成業務超時,但是業務超時的原因不一定是丟包。原因前面也提到過,包括鏈路上的硬件轉發或路由等設備,以及其上的系統及應用軟件的每一個環節都存在引起業務超時的情況。

2.3 網絡抖動的衡量指標

衡量“網絡抖動”的指標,大家能想到的肯定是看業務的請求和回覆報文的延遲是多少,即 latency 或者 RT(Reponse Time),在雲計算場景中,具體化到了一些特定的網絡指標,比如 RT、請求數、連接數、bps、pps 等。其中一些指標的含義如下:

1. 響應時間(RT Response Time)

響應時間是指執行一個請求從開始到最後收到響應數據所花費的總體時間,即從客戶端發起請求到收到服務器響應結果的時間。RT 是一個系統最重要的指標之一,它的數值大小直接反映了系統的快慢。

對於一個遊戲軟件來說,RT 小於 100 毫秒應該是不錯的,RT 在 1 秒左右可能屬於勉強可以接受,如果 RT 達到 3 秒就完全難以接受了。而對於編譯系統來說,完整編譯一個較大規模軟件的源代碼可能需要幾十分鐘甚至更長時間,但這些 RT 對於用戶來說都是可以接受的。所以 RT 的多少,對不同系統的感受是不一樣的。

2. 吞吐量(Throughput)

吞吐量是指系統在單位時間內處理請求的數量。

系統的吞吐量(承壓能力)與 request 對 CPU 的消耗、外部接口、IO 等緊密關聯。單個 request 對 CPU 消耗越高,外部系統接口、IO 速度越慢,系統吞吐能力越低,反之越高。影響系統吞吐量幾個重要參數:QPS(TPS)、併發數、響應時間。

3. 併發數

併發數是指系統同時能處理的請求數量,這個也是反映了系統的負載能力。一個系統能同時處理的請求數量,連接數量都有一個規格要求,當請求數越多時,系統處理的速度就會出現瓶頸。

4、QPS 每秒查詢數量(Query Per Second)

QPS 是一臺服務器每秒能夠響應的查詢次數,是對一個特定的查詢服務器在規定時間內所處理流量多少的衡量標準。

5、TPS 每秒執行的事務數量(throughput per second)

TPS 代表每秒執行的事務數量,可基於測試周期內完成的事務數量計算得出。一個事務是指一個客戶機向服務器發送請求然後服務器做出反應的過程。例如,用戶每分鐘執行 6 個事務,TPS 爲 6 / 60s = 0.10 TPS。

指標:

  • QPS(TPS):每秒鐘的請求/事務數
  • 併發數:系統同時處理的請求/事務數
  • 響應時間:一般取平均響應時間

這三者之間的關係:

  • QPS(TPS) = 併發數/平均響應時間
  • 併發數 = QPS * 平均響應時間

爲了描述更廣泛意義上的網絡抖動,雲場景中我們一般用 RT 這個術語,我們會有監控檢測某個業務的 RT 值,比如 nginx 服務的 RT 值。一般本文所述的延遲、超時、響應慢、卡頓等詞彙,只要影響到了用戶的體驗,都認爲是抖動問題。

下圖是衡量指標的彙總:

三、 Linux 內核網絡抖動

3.1內核網絡抖動點

用戶的業務部署在雲上,一般運行在容器裏或者直接部署在 guest OS 上,前面也提到過,操作系統內部、業務進程的調度運行、業務的請求和處理也會存在網絡抖動的點。其中,報文的收發過程也存在諸多耗時的地方。首先看一個 Linux 內核網絡協議棧的分層架構圖。

我們先來回顧一下 Linux 的網絡收包流程

1、數據報文從外部網絡到達網卡。

2、網卡把數據幀通過 DMA 送到系統內存保存。

3、硬中斷通知 CPU 有報文到達。

4、CPU 響應硬中斷,簡單處理後發出軟中斷。

5、軟中斷或者通過 ksoftirqd 內核線程處理報文,然後通過網卡 poll 函數開始收包。

6、幀被從 Ringbuffer 上摘下來保存爲一個 skb。

7、協議層開始處理網絡幀,經過 netdev、IP、tcp 層處理。

8、協議層處理完之後,把數據放在 socket 的接收隊列中,然後通過喚醒用戶進程來進行收包。

9、用戶進程經過操作系統的調度獲得 CPU,開始從內核拷貝數據包到用戶態進行處理。

Linux 網絡的發包流程如下:

1、應用程序通過 send 系統調用發送數據包,從用戶態陷入到內核態,內核會申請一個 sk_buff,然後將用戶待發送的數據拷貝到 sk_buff ,並將其加入到發送緩衝區。

2、網絡協議棧從 Socket 發送緩衝區中取出 sk_buff,並按照協議棧從上到下逐層處理,最後報文進入網絡接口層處理。

3、網絡接口層會通過 ARP 協議獲得下一跳的 MAC 地址,然後對 sk_buff 填充幀頭和幀尾,接着將 sk_buff 放到網卡的發送隊列中,一般使用 qdisc 設置排隊規則,進行入隊和出隊處理。

4、網卡驅動會從發送隊列中讀取 sk_buff,將這個 sk_buff 掛到 RingBuffer 中,接着將 sk_buff 數據映射到網卡可訪問的內存 DMA 區域,最後觸發真實的發送。

5、當發送完成的時候,網卡設備會觸發一個硬中斷來釋放內存,主要是釋放 sk_buff 內存和 RingBuffer 內存的清理。

處理流程如下圖所示,數字編號不一定完全對應。

 

上面所述的報文收發過程,存在網絡抖動的地方是:協議棧和驅動的入口和出口處,以及內核態和用戶態的銜接處。比如接收報文到達後發出中斷到報文真正得到處理這段時間的耗時,這個耗時很多時候都是由於某個進程長時間關中斷導致中斷和軟中斷處理延遲;另一個是數據到達接收隊列後,喚醒用戶進程到真正調用 recvmsg 收包處理的這段時間的耗時,這個主要由於系統繁忙而出現調度延遲,被喚醒的進程長時間未能真正去處理收到的包。

因此,Linux 內核裏,網絡抖動一般是在中斷和軟中斷處理的延遲,進程的睡眠和喚醒延遲,qdisc 排隊延遲,Netfilter 處理延遲,tcp 的超時重傳延遲等。

3.2 三類抖動的根因探尋和解決之道

雲計算涉及到的網絡節點較多,且每個點都有發生抖動的可能,限於篇幅,同時由於操作系統和業務最貼合,本文只基於節點內部操作系統的視角。針對前面提到的三類抖動:當前抖動、歷史抖動、ping 毛刺,來討論一下如何去發現和解決這三類抖動的問題。

經過我們在實踐中的摸索和分析總結,提出以下抖動根因的探測方法和抖動問題解決之道:

1. 針對 Ping 毛刺問題,提出在用戶態構造報文進行探測的方法:Pingtrace。不同於大家常用的 ping 程序,Pingtrace 通過在 icmp/tcp/udp 的基礎上增加 pingtrace 協議頭,在 pingtrcace 報文沿途經過的節點填上對應的收發時間戳,最後通過計算各個節點的延時信息,構建一個拓撲來描繪節點詳細信息,從而找到抖動的節點和抖動原因。

2. 針對當前抖動問題,對真實報文直接跟蹤挖掘時延:Rtrace。它對真實業務報文所經過的內核處理函數特別是協議棧處理函數進行 tracing, 得到每個函數點的時間戳信息,支持 icmp/tcp/udp/lacp/arp 等協議報文調用路徑的獲取和時延信息的統計,還能清楚知道某個協議包在哪裏由於什麼原因丟包的,或者哪個函數處理慢了。

3. 針對歷史抖動問題,提出常態化抖動監控系統:Netinfo。它對容器(pod)、流、邏輯接口的各項指標進行監控,追蹤業務抖動的根因,進行集羣和單機的告警上報。深度加工丟包、重傳、擁塞控制、窗口變化、流量突發、中斷延遲等指標進行分析,歸一化成簡單的健康度指標;同時在數據處理中心進行離羣檢測,找出影響抖動的幾個重點指標和具有集羣共性的指標。

4. 針對不同的業務應用,提出應用觀測引擎 Raptor。業務應用的內在問題是客戶直接能看到的,但是如何與系統指標關聯,是當今觀測領域的難點,它通過把應用內部的細節進行展開,結合系統的 profiling 剖析,能找到應用抖動的密碼。

通過網絡抖動三劍客和應用觀測引擎 Raptor,我們能系統的監控和觀測在節點內部出現的抖動,同時能定界出是業務應用自身的問題,還是外部網絡的問題。下面的章節我們將簡單介紹網絡抖動三劍客的原理。(關於應用觀測引擎 Raptor,限於篇幅會另外組織一個專題介紹)

四、瞬時毛刺的主動探測:Pingtrace

4.1 背景

在碰到網絡聯通性較差或者系統比較卡時,我們喜歡用系統自帶的 ping 命令向目標地址發送請求包進行檢測,然後通過目標機回覆的響應包來判斷是否出現了延遲,這種方法簡單又高效。但有時我們想知道,這個 ping 包延遲了,和業務的關係怎樣?是否延遲高了或者又丟包了,業務應用就真的出問題了?延遲和丟包的具體點在什麼地方?是系統內部還是外部鏈路?原因是什麼?

經過這麼幾個靈魂拷問之後,我們發現,對於瞬時 ping 延遲突然衝高的問題(ping 毛刺),傳統的 ping 工具已經不能直觀的拿到背後的信息。爲此我們提出了通過構造新報文(pingtrace 報文)的方式進行主動的探測,通過在 pingtrace 沿途經過的點填充 timestamp 的方式,把系統內部的延遲精細化到用戶態和內核態的函數處理點,然後通過可視化方式展現延遲高的模塊。

4.2 pingtrace功能介紹

Pingtrace 通過在用戶態構造探測協議報文,在獨有的 pingtrace 頭部增加 icmp、 tcp 及 udp 協議頭,可以進行多種協議探測,同時基於 eBPF 技術,可以做到無侵入的方式實現系統內部細節的窺探,開銷遠遠小於 tcpdump 等已有工具,並可實時展示各個數據鏈路的時延信息,快速發現問題邊界。

下圖是 icmp pingtrace 的協議實現(icmp 頭可以替換爲 tcp 和 udp 協議頭)。在各個節點,要求其他節點捕獲到特定 pingtrace 報文時填入 node id 和 timestamp(變通的實現方法是通過 eBPF 把報文送到用戶態,然後補發帶有 timestamp 的報文回送到源端),爲了讓報文儘可能小於 1500 個字節,可以通過控制表項數量來避免沿途的 IP 報文分片。

下圖是其工作過程:

下圖是最終呈現出來的效果,每個藍點地方鼠標放過去會顯示延時信息:

注意:很多人關心發送端和接收端的時鐘源不統一,如何來進行延遲節點的判定。我們在邊界點採取了相對延遲的計算方法,而不是像其他幾個點的絕對延遲計算方法。

計算方法如下:通過對邊界的兩個採集點時間戳信息計算出差值,以最近 100 個報文中最小的差值作爲基準值,對下一個報文的差值進行校正(校正就是用當前算出來的兩臺機器時間戳差值相減得到 delta,減去基準值 base 算出來的結果),最後得到相對延遲。如果發現相對延遲較高,則說明鏈路上出現了問題。

這個是 udp 的 pingtrace 探測:

這個是 tcp 的 pingtrace 探測:

tcp 和 udp 的延遲探測,主要目的是爲了探測系統 tcp 和 udp 處理路徑是否出現延遲,因爲絕大部分業務都會採用 tcp 和 udp(icmp pingtrace 不能滿足此需求),由於端口號的原因,它主要多了一個端口探測和學習的過程。

4.3 pingtrace 如何進行探測

具體的使用上,有界面和命令行兩種方式。界面方式只需要填入對應的源和目的 IP,它會自動下發安裝命令到 client 和 server,然後開始進行診斷,診斷結果可以直接呈現是哪個節點的哪個階段出現的延遲。

或者通過命令行方式:

sysak pingtrace_raw -c 127.0.0.1 -m 1000 -o log

5. 真實業務報文延遲挖掘:Rtrace

使用自定義報文探測方式雖然可以瞭解當前的系統負載和鏈路情況,但很難說明對某個業務或者協議是否真的有影響,所以我們還需要對實際業務的報文,包括 tcp 、udp、icmp、arp 及 lacp 等報文進行跟蹤確定報文走的路徑和每個函數的耗時。

rtrace 是一款基於 eBPF 的網絡診斷工具,利用 eBPF 技術動態打點來取得報文時間信息,以及每個網絡層的詳細信息,比如 tcp 常見的 memory 使用情況,擁塞和回覆 ack 情況,記錄在日誌裏,可以輔助問題的定界和丟包查看。如下圖,rtrace 監控的部分協議棧處理函數點:

在雲計算的集羣環境裏,抓取到的單個節點的延時和 tcp 連接信息,有時還是很難去判斷是否真的有問題,如果能從集羣的維度,或者多個節點的共性事件的方式,或許能收穫更多。rtrace dump 功能還支持集中式抓包的能力,類似一鍵發起抓包功能,然後進行集中式分析,比如分析 tcp 的發送接和接收到 ack 時間,到底是慢在哪個節點上,通過對比 tcp 的 sequence 來彙總數據,很快就能得到結果。

6. 歷史抖動監控:Netinfo

歷史抖動問題,是幾種抖動問題裏最難解決的,由於問題不再復現,我們能想到的是增加一些監控手段,把歷史某個時間點的系統狀態、協議交互情況等信息收集起來是不是就能解決抖動問題了?答案是否定的。如果單純從網絡本身的丟包和 tcp 連接狀態信息來判斷,顯然還不夠。還需要看當時 IO 是否 hang 住,內存是否 oom,系統是否宕機,中斷是否有突發,調度是否延遲等。

如何在上百個指標中快速找到異常點?Netinfo 在檢測到抖動後(業務的 RT 值或者健康度指標),會先彙集所有指標進行組合,進行離羣檢測。最終把集羣裏的共性事件,通過離羣統計算法來確定抖動根因。

Netinfo 主要由數據採集和數據分析告警兩部分功能組成:

關於 Netinfo 可以參考文章 Netinfo:揭開網絡抖動面紗的神器。Netinfo 的功能,後面會移到 SysAK 裏,同時,後端的數據處理部分,也會移到 SysOM 統一平臺分析。

SysOM 平臺鏈接地址:http://www.sysom.pro/welcome

7. 網絡抖動探測標準化設想及未來展望

藉助於網絡抖動三劍客(Pingtrace、Rtrace、Netinfo),我們很容易知道系統的抖動點和原因。但是這些可能只是我們自己的理解,我們基於雲場景做了很多探索,並把這些探索沉澱到了龍蜥操作系統,還進行了很多優化。而目前操作系統呈現百花齊放的態勢,網絡抖動的發現和檢測方法不統一,將很難在一些指標評測和系統對接時,有一個有效的驗收標準。因此我們覺得有必要形成一個標準,比如:

1)雲計算場景下抖動的定義和表現是什麼?不同類型的業務有什麼具體現象就算是抖動了?

2)抖動包含哪些內容和衡量指標?指標的範圍是什麼?

3)如何檢測網絡抖動?有沒有統一的工具進行探測?探測哪些點合適?

4)需要在哪些點增加時間戳統計?比如 Linux 用戶態到內核態的發包點,網卡的發包點。

針對網絡抖動,每個人的理解可能不一樣,上文 2.1 節提到抖動的幾個現象,就是具體的案例。如果能結合具體的指標去衡量,就會有很大的可實操性。比如 RT 這個指標,我們選擇 nginx 的業務作爲衡量對象,RT 在多少範圍算是異常的?10ms 或者 100ms 都可能,關鍵評判是不同用戶場景,是否這個 RT 值影響到了用戶體驗,如果用戶體驗很差,就認爲是發生了抖動。

當然最重要的,我們需要制定出一套方案和工具去進行探測,只要工具說探測到 nginx 業務的 RT 指標高了,那麼就說明在同一個系統負載下,你的整個雲服務網絡抖動大,網絡質量不太好,這個時候我們就要根據探測到的根因去解決問題。

回到操作系統層面,我們需要指定哪些探測點呢?只有大家形成一個統一認識,在Linux 內核收發包的出入口進行時間戳信息的提取是合適的。例如在內核 sendmsg 系統調用函數和網卡發包的地方(比如 virtio-net 的 start_xmit 函數)增加時間戳信息。這樣大家實現的工具,就能統一到一個衡量維度。

比如,我們在 virtio-ne 驅動裏,我們也在積極推動增加一個時間戳的點,將有助於我們在發包處時間戳的統一:

+#define VIRTIO_NET_HDR_F_TSTAMP        8

最後做一個總結,抖動的檢測和治理是一個長期的任務,如果能將 Linux 系統內部的檢測工作標準化起來,將有助於我們制定統一的性能評測方案,以及運維自動化的實現。

另外,上述工具幾乎全部採用無侵入的方式實現,基於eBPF實現給了我們很大的發揮空間,它們將會在 SyaAK 裏全部開源(目前已大部分開源)敬請關注,後面也會有系列文章再次詳細介紹。

相關鏈接地址:

SysAK 的開源項目鏈接:[email protected]:anolis/sysak.git

SysOM 的運維平臺鏈接:[email protected]:anolis/sysom.git

文/eBPF 技術探索 SIG

原文鏈接

本文爲阿里雲原創內容,未經允許不得轉載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章