日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

直播回顾:如何对付臭名昭著的 IO 夯?诊断利器来了 | 龙蜥技术

發布時間:2024/8/23 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 直播回顾:如何对付臭名昭著的 IO 夯?诊断利器来了 | 龙蜥技术 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡介:聽到IO夯總是讓人頭疼,那有沒有可以分析IO夯問題的利器?

編者按:sysAK(system analyse kit),龍蜥社區(OpenAnolis)系統運維 SIG 下面的一個開源項目,聚集阿里百萬服務器的多年運維經驗,針對不同的運維需求提供了一系列工具,形成統一的產品進行服務。作者總結了實際工作中處理的 IO 夯問題的經驗,將它梳理成一套理論分析方法并形成 iosdiag 工具,集成到了sysAK 工具集里。本文將由作者帶大家一道領略一下 iosdiag 在 IO 夯領域叱咤風云的魅力。本文整理自龍蜥大講堂第三期技術解讀,直播回顧可在龍蜥社區官網查看。

作者:李光水(君然)系統運維SIG核心成員、 毛文安(品文)系統運維SIG負責人。

一、引言

這是作者第二次備戰雙十一,懷著激動的心情迎接雙十一的到來,不曾想迎來的是一枚深水炸彈:趕緊處理一下業務那邊出現的 Load 高問題。

“為什么 Load 高呢?”

“因為有 500 多個進程變成了 D 狀態。”

“那為什么會有這個多進程 D 狀態呢?”

“因為出現了 IO 夯問題...”

曾幾何時,聽到 IO 夯,作者會有點頭皮發麻,為啥呢?因為沒有有效手段去定位這個問題,或者就算是有手段,也得經歷山路十八彎,成不成還的看運氣,若是幸運,還能分析點啥出來,若是不幸運,把機器整掛掉,得不償失。時至今日,遇到 IO 夯問題再也不虛了,因為作者現在手里有可以分析 IO 夯問題的利器——sysak iosdiag

先來看看這個棧,500 多個進程是因為在內核下等待某個磁盤的塊設備互斥鎖而進入 D 狀態,如圖 1-1 所示:

圖 1-1

互斥鎖正被執行讀 IO 請求的內核進程 kworker 持有,如圖 1-2 所示,只有讀 IO 流程完成之后才能釋放鎖。但是因為 IO 夯住了,讀 IO 流程無法順利完成,所以就沒法正常釋放鎖了。所以接下來就需要找到是訪問哪塊磁盤出現了 IO 夯?IO 究竟夯在哪里?

圖1-2

之后作者使用 sysak iosdiag 工具找到了出現 IO 夯問題的磁盤,同時也定位出來這個 IO 是夯在了磁盤側,如圖 1-3 所示:

圖1-3

作者通過查詢 virtio 的后端磁盤的硬件隊列的 IO 信息,發現 IO 實際已經處理完了,進一步查詢 vring 信息,發現后端沒有更新 used ring,最終將問題原因鎖定到了 virtio 后端。最后此問題的具體修復方法我們在此不再一一表述,總之,該工具可以方便的定界到問題出自前端驅動還是后端設備側,節省了不少人力。

經過此問題,作者也簡單做了下總結,聊一下 IO 夯的那些事。

二、史詩級的IO架構

在聊 IO 夯之前,了解一個 IO 會經過哪些路徑還是很有必要的。網上有各式各樣的 IO 架構圖,足以讓人看到眼花撩亂;作者從一個 IO 的生命周期的角度畫了一幅圖,然后描述一個 IO 在不同階段的那些事兒(下圖中去掉了部分軟件層次,如 dm、lvm 等),流程有點長,請耐心看完~

圖 2-1

  • 假設我們以一次用戶態程序的寫 IO 為例,那么在調用 write 時候會傳入一個數據 buf,這個 buf 在內核層面也是有對應page的。在默認情況下,IO 會以 buffer io 方式往下走;
  • 假設以 buffer io 方式往下走,走到文件系統層,會將 1 中 buf 里面的數據拷貝到內核 page cache 中,然后把這些 page 置臟,如果此時系統的臟頁水位還沒有達到系統所設置的閾值,這里就返回了,對用戶而言這次 IO 結束了;如果此時臟頁水位達到系統所設置的閾值,那么就會啟動刷臟流程,這里根據臟頁水位具體達到的不同閾值,對用戶進程會有不同的處理策略,如短暫休眠或不休眠,在此之后依舊會返回,用戶一次 IO 結束;
  • 刷臟是通過 writeback 機制進行,這一流程的觸發,可能是通過定期觸發,或者如 2 所說水位已經超過系統所設定的閾值了,又或者是用戶執行了同步命令或者調用了 sync/fsync 之類的 api 等等。writeback 機制將臟頁回寫包裝成一個個 work,然后這些 work 由系統的 worker 進程,也就是內核的 kworker 進程來執行。刷臟的過程以一個個 inode 為單位,然后將其中的臟頁進一步包裝成 bio 結構(bio 結構中,會有一個 bio_vec 來描述被包裝的臟頁 page,簡單理解就是會有一個 page 指針指向這個臟頁),之后將 bio 提交到 block 層;當然如果此次 IO 涉及到文件系統元數據的變更,中途內核進程 jbd 也會往 block 層提交 bio;
  • bio 進入 block 層之后會經歷一系列的限制性的處理,如這個 bio 所包裝的數據長度是否過大,有或者是否已經觸發到 IO 限流,因為這些機制有點小復雜,就不在圖上展示了。在此之后,會嘗試與已有的 IO 請求進行合并,具體合并則根據 bio 所描述磁盤上起始扇區和長度與 IO 請求中 bio 描述的磁盤地址是否連續來進行合并。如能合并就不再往下,直接返回了;
  • 如不能合并,則申請一個新的 IO 請求,在多隊列架構中,根據磁盤的隊列個數和隊列深度,在磁盤初始化階段,在內存上對每條硬件隊列已經預先分配了一個 request 集合,同時會有對應的 bitmap 來表示每個請求是否已經被申請。當沒有請求可以被申請到時,說明此隊列上的 IO 請求已經滿了,申請的進程將進入深度休眠等待隊列上的 IO 請求已經成功刷到磁盤并釋放 IO 請求,才能申請到;
  • 申請到之后,將 bio 包裝成 IO 請求——request,將 IO 請求添加到進程的 plug 隊列中,當積蓄到一定量的 IO 請求之后,一把“泄洪”到派發隊列上;(補充說明:plug隊列“蓄流”機制屬內核行為,用戶無法控制,plug 隊列能積累的 IO 請求數也是有限制的;觸發“泄洪”,有可能是 plug 隊列滿了自己觸發的,也有可能是提交完一段數據之后,主動調用的內核接口觸發);
  • request 進入派發隊列之后,會被派發到驅動層,上圖以 virtio blk 為例,request 會被封裝成一個個 sg,這些 sg 里面有描述數據 page 的物理地址、本次 IO 訪問的磁盤起始扇區、數據長度等信息。之后驅動將 sg 推入到 vring 緩存中,vring緩存在主機上,是主機上 virtio blk 前端和后端磁盤共享的一塊可 dma 訪問的內存。sg 推入 vring 之后,會 kick 磁盤提取 IO 并通過 dma 完成數據傳輸,IO 完成之后,磁盤給主機一個中斷,virtio blk 驅動從 vring 中取出完成的 request,進入 io cpmplete 路徑;
  • request 進入 io complete 路徑之后,首先執行在 bio 結構體中設置的回調函數,這些回調函數一般在創建 bio 的的流程中指定,其一般負責喚醒等待進程、釋放鎖資源的操作;之后會記錄 io stat 信息,這些信息也是系統 iostat 工具的指標來源;最后釋放掉 request,這個釋放并不是將 request 內存清空,而是清除該 reqeust 對應的在硬件隊列 request 集合上的 bitmap 位,以便于后來的 IO 可以再去申請使用;
  • 至此,一個 IO 的生命周期結束,而對于 direct io 的方式,整個過程會缺少數據buf復制到內核 page cache、臟頁回寫這個步驟。上面提到的流程可能不是一個完成 IO 生命周期的全部,由于 IO 鏈路的復雜性,中間也省掉了部分流程,有興趣的讀者可以再去摸索摸索,或者加入我們系統運維 sig 交流群,歡迎一起探討。
  • 三、臭名昭著的IO夯

    3.1 何為IO夯

    IO 夯,可簡單理解為 IO 路徑在一定程度上堵住了,輕則經過特定路徑的 IO 不可訪問,重則整條 IO 路徑堵住不可用,任你多少 IO 丟下來,我就是沒反應。為什么 IO 路徑會堵住呢,無外乎是在等待資源。

    等待資源一般涉及的是 IO 路徑上不可重入的臨界區,要求進程持有資源進入、釋放資源退出,又或者是事物處理型,允許接受有限個進程的事物,但要等待這些進程的事物全部被處理完之后,才能接收新的進程事物,開始處理新一輪的流程。而當處于臨界區內的進程,由于內核 bug 或存儲介質原因,導致無法順利完成 IO 后正常退出,最終造成臨界區外的進程因為拿不到資源而處于阻塞狀態,導致無 IO 可用。由此可見,只要臨界區內的進程不退出這種尷尬的狀態,整條 IO 路徑就不可用。

    圖 3-1

    內核下有條 io complete 的關鍵路徑,這條路徑屬于可重入路徑,其主要職責為對 IO 結束后的收尾工作,一般地,會先執行一個 IO 回調流程,而后更新一些 IO 的stat信息,最后結束生命周期。內核中也有一些特殊類的 IO,在 IO 子系統中的處理方式與一般的 IO 有所差異,如 flush/fua io,而作者曾經碰到過一起 flush/fua io 夯的問題。flush/fua io 在使用日志型的文件系統場景下可能會比較常見,如 ext4 文件系統,為了保證文件系統元數據能夠真正的持久化存儲到磁盤的日志區域,jbd 線程在提交 commit record 的時候會發起這種 IO,而flush/fua io的處理流程也是比較繁瑣的:

    圖 3-2

    如上圖所示,IO 子系統在處理這個 IO 時,會先發起一個 flush io 到磁盤(在內核中喚作pre-flush),等這個 IO 結束之后,再發起真正的數據 IO,當磁盤執行完數據 IO 之后,再此發起一個flush io(在內核中也喚作 post-flush),終于 flush io 結束之后,數據 IO 進入complete 路徑。在這個數據 IO 里面,一般會存在比較關鍵的 IO 回調,其涉及到釋放 buffer head 的 lock bit 或者 page cache 的 lock bit,而且往往等待這個 lock bit 的是 jbd 線程本身;作者曾經就遇到 pre-flush io 因為 race 問題被直接釋放掉了,導致后續的 IO 流程沒有走到,data io 沒有得到處理,buffer lock 得不到釋放,造成 jbd 夯住,最終引起這個分區的 IO 都得不到響應。

    經過本小節的介紹,結合章節 2 的 IO 結構圖(圖 2-1),可以發現 IO 夯是可以發生 IO 路徑上的任何地方

    3.2 IO夯的危害

    從 3.1 可知,IO 夯會造成有 IO 需求的進程無 IO 可用;從業務穩定性角度來看,對于那些有 IO 訪問需求的業務進程,IO 夯可能會引起進程長期阻塞,且在 IO 路徑恢復之前,都無法對外提供服務。從系統穩定性角度來看,IO 夯可能會引起大量的進程進入 D 狀態,導致系統高負載,甚至系統夯住,shell 命令無法執行,機器無法登陸,最終不得不重啟系統去解決。

    3.3 IO夯問題分析方法現狀

    當遇到 IO 夯問題時,我們通常會分析 dmesg 中 hungtask 調用棧、或者是 iosta 信息、sysfs/debugfs 中的統計信息,再結合以往經驗去推測問題可能出在哪。當我們碰到如下圖 3-3 所示的 iostat 信息時,根據經驗,會懷疑是磁盤側有 IO 沒回,因此懷疑io夯在磁盤上,讓存儲的同學去排查磁盤側。但這種經驗卻不一定靠譜,如果是在磁盤返回到 io complete 之間有內核 bug,iostat 也會出現下圖中的信息。

    圖 3-3

    那如何分析 IO 夯問題是最有效的呢?答案肯定是要找出來夯住的 IO 請求,然后根據請求里面的信息去分析當前這個請求是處于什么狀態、已經走到哪個路徑了。但遺憾的是,目前沒有實現這個功能的通用工具,唯一能快速實現這一需求的,就只有對問題現場做 crash 分析了,找到夯住的 IO 請求,根據 IO 請求中的信息,再結合代碼流程,一步步深入最終找到問題原因,但前提是業務可以容忍這么操作。

    3.4 利器簡介——sysak iosdiag

    sysAK iosdiag,是 sysAK 工具平臺中的 IO 診斷工具,已具備 IO 時延探測、IO 夯診斷兩大功能,其中 IO 夯診斷可用于檢測當前系統中 IO 夯事件并確定問題邊界。工具的大體架構圖 3-4 所示:

    圖 3-4

    首先通過 sysAK 的 iosdiag 功能去使能 IO 夯診斷,這里診斷到 IO 夯之后,會對 IO 進行數據分析,然后形成診斷結論,診斷結論是以 json 的數據格式保存在一個日志文件里面,同時也支持將數據上傳到指定的地方,目前支持 oss 的上傳方式,不上傳的話,數據也會存在機器本地,供調用者去查看。

    圖 3-5

    工具的性能開銷情況:單核 cpu 低于 1%、內存消耗低于 10MB、消耗少許磁盤空間保存診斷結果。

    工具支持的內核版本種類:3.10/4.9/4.19多種版本。

    iosdiag 診斷結果輸出,力求信息準確、結果直觀,期望即便不具備內核IO子系統知識的同學也能快速上手。工具會輸出一些結論性的信息,如什么時間點,檢測到了 IO 事件,這是一個什么樣的 IO,從哪個 cpu 發出來的,從哪個磁盤的哪個位置訪問多大的數據量,然后這個 IO 夯在哪個路徑上,夯住了多久。

    圖 3-6

    四、TODO

    工具目前只能覆蓋到進入內核 block 層的 IO,在 block 之上的覆蓋不到,因此作者目前也在研究如何擴大工具的覆蓋面;其次,工具在結果輸出上還不夠直觀,使用者還無法簡單明了地從輸出信息上看到問題,針對這一點,作者也一直在優化。

    原文鏈接
    本文為阿里云原創內容,未經允許不得轉載。?

    總結

    以上是生活随笔為你收集整理的直播回顾:如何对付臭名昭著的 IO 夯?诊断利器来了 | 龙蜥技术的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。