SysOM 案例解析:消失的記憶體都去哪了 !| 龍蜥技術
文/系統運維 SIG
在《AK47 所向披靡,記憶體洩漏一網打盡》一文中,我們分享了slab 記憶體洩漏的排查方式和工具,這次我們分享一種更加隱秘且更難排查的"記憶體洩漏"案例。
一、 問題現象
客戶收到系統告警,K8S 叢集某些節點 used 記憶體持續升高,top 檢視程式使用的記憶體並不多,剩餘記憶體不足卻找不到記憶體的使用者,記憶體神秘消失,需要排查記憶體去哪兒了。
執行 top 指令並按記憶體排序輸出,記憶體使用最多的程式才 800M 左右,加起來遠達不到 used 9G 的使用量。
二、問題分析
2.1 記憶體去哪兒了?
在分析具體問題前,我們先把系統記憶體分類,便於找到記憶體使用異常的地方,從記憶體使用性質上,可以簡單把記憶體分為應用記憶體和核心記憶體,兩種記憶體使用量加上空閒記憶體,應該接近於 memory total,這樣區分能夠快速定位問題的邊界。
其中 allocpage 指透過 __get_free_pages/alloc_pages 等 API 介面直接從夥伴系統申請的記憶體量(不包含 slab 和 vmalloc)。
2.1.1 記憶體分析
根據記憶體大圖分別計算應用記憶體和核心記憶體,就可以知道是哪部分存在異常,但這些指標計算比較繁瑣,很多記憶體值還存在重疊。針對這個痛點,SysOM 運維平臺的記憶體大盤功能以視覺化的方式展示記憶體的使用情況,並直接給出記憶體是否存在洩漏,本案例中,使用 SysOM 檢測,直接顯示 allocpage 存在洩漏,使用量接近 6G。
2.1.2 allocpage 記憶體
那既然是 alloc page 型別的記憶體佔用多,是否可以直接從 sysfs、procfs 檔案節點檢視其記憶體使用了?很遺憾,這部分記憶體是核心/驅動直接呼叫 __get_free_page/alloc_pages 等函式從夥伴系統申請單個或多個連續的頁面,系統層面沒有介面查詢這部分記憶體使用詳情。如果這類記憶體存在洩漏,就會出現"記憶體憑空消失"的現象,比較難發現,問題原因也難排查。針對這個難點,我們的SysOM 系統運維能夠覆蓋這類記憶體統計和原因診斷。
所以需要進一步透過 SysOM 的診斷利器 SysAK 動態抓取這類記憶體的使用情況。
2.2 allocPage 型別記憶體排查
2.2.1 動態診斷
對於核心記憶體洩漏,我們直接可以使用 SysAK 工具來動態追蹤,啟動命令並等待 10 分鐘。
sysak memleak -t page -i 600
診斷結果顯示 10 分鐘內 receive_mergeable 函式分配的記憶體有 4919 次沒有釋放,記憶體大小在 300M 左右,分析到這裡,我們就需要結合程式碼來確認 receive_mergeable 函式的記憶體分配和釋放邏輯是否正確。
2.2.2 分配和釋放總結
1)page_to_skb 每次會分配一個線性資料區為 128 Byte 的 skb。
2)資料區呼叫 alloc_pages_node 函式,一次性從夥伴系統申請 32k 記憶體(order=3)。
3)每個 skb 會對 32k 的 head page 產生一次引用計數,也就是隻有當所有 skb 都釋放時,這 32k 記憶體才釋放回夥伴系統。
4)receive_mergeable 函式負責申請記憶體,但不負責釋放這部分記憶體,只有當應用從 socket recvQ 中把資料讀走才會對 head page 引用計數減一,當 page refs 為 0 時,釋放回夥伴系統。
當應用消費資料比較慢,可能會導致 receive_mergeable 函式申請的記憶體釋放不及時,而且最壞情況一個 skb 會佔用 32k 記憶體,使用 sysak skcheck 檢查 socket 接收佇列和傳送佇列殘留情況。
從輸出可以知道,系統中只有 nginx 程式的接收佇列有殘留資料,socket fd=11 的 Recv-Q 有接近 3M 的資料沒有接收,透過直接 kill 146935,系統記憶體恢復正常了,所以問題根本原因就是 nginx 沒有及時收走資料了。
三、問題結論
經過與業務方溝通,最終確認是業務配置問題,導致 nginx 有一個執行緒沒有處理資料,從而導致網路卡驅動申請的記憶體沒有及時釋放,而 allocpage 記憶體又是無法統計的,從而出現記憶體憑空消失的現象。
結論驗證
接收佇列真的有資料殘留嗎,這裡結合 crash 工具的 files 指令透過 fd 找到對應的sock:
socket = file->private_data sock = socket->sk
透過多次觀察,發現 sk_receive_queue 上的 skb 長時間沒有變化,這也證明了 nginx 沒有及時處理接收佇列上的 skb,導致在網路卡驅動中分配的記憶體沒有釋放。
四、記憶體洩漏疑點
在排查過程還遇到一個非常較困惑的地方,sockstat 和 slabtop 看檢查 tcp mem 和 skbuff_head_cache 使用都很正常,導致進一步掩蓋了網路佔用的記憶體。
tcp mem = 32204*4K=125M
skb 數量在 1.5萬~3 萬之間。
按照前面分析,一個skb最壞情況佔用 32k 記憶體,那麼 2 萬個 skb 最大也就佔 600M 左右,怎麼會佔用幾個 G 了,難道分析有問題?如下圖所示,skb 的非線性區可能還存在若干個 frag page,而每個 frag page 又可能由 compund page 組成。
用 crash 實際讀取 skb 記憶體發現,有些 skb 存在 17 個 frag page,並且資料大小隻有 10 Byte。
解析 frag page 的 order 為 3,意味著一個 frag page 佔用 32k 記憶體。
極端情況下,一個 skb 可能佔用(1+17) 8=144 頁,上圖 slabinfo 中skbuff_head_cache 活躍 object 數量為 15033 個,所以理論最大總記憶體 =14415033*4K = 8.2G,而我們現在遇到的場景消耗 6G 的記憶體是完全有可能的。
—— 完 ——
加入龍蜥社群
加入微信群:新增社群助理-龍蜥社群小龍(微信:openanolis_assis),備註【龍蜥】與你同在;加入釘釘群:掃描下方釘釘群二維碼。歡迎開發者/使用者加入龍蜥社群(OpenAnolis)交流,共同推進龍蜥社群的發展,一起打造一個活躍的、健康的開源作業系統生態!
關於龍蜥社群
龍蜥社群(OpenAnolis)由企事業單位、高等院校、科研單位、非營利性組織、個人等在自願、平等、開源、協作的基礎上組成的非盈利性開源社群。龍蜥社群成立於 2020 年 9 月,旨在構建一個開源、中立、開放的Linux 上游發行版社群及創新平臺。
龍蜥社群成立的短期目標是開發龍蜥作業系統(Anolis OS)作為 CentOS 停服後的應對方案,構建一個相容國際 Linux 主流廠商的社群發行版。中長期目標是探索打造一個面向未來的作業系統,建立統一的開源作業系統生態,孵化創新開源專案,繁榮開源生態。
目前,Anolis OS 8.6已釋出,更多龍蜥自研特性,支援 X86_64 、RISC-V、Arm64、LoongArch 架構,完善適配 Intel、兆芯、鯤鵬、龍芯等晶片,並提供全棧國密支援。
歡迎加入我們,一起打造面向未來的開源作業系統!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70004278/viewspace-2904643/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Redis記憶體——記憶體消耗(記憶體都去哪了?)Redis記憶體
- 致敬 hacker :盤點記憶體虛擬化探索之路|龍蜥技術記憶體
- 從新手小白到運維大咖,SysOM 多場景當機例項解析 | 龍蜥技術運維
- 那些到了 30 歲的技術人,後來都去哪了?
- 這 8 類問題,SysOM 2.0 OOM 診斷助你快速定位異常 | 龍蜥技術OOM
- 記憶體不超過5M,datop 在識別冷熱記憶體及跨 numa 訪存有多硬核?| 龍蜥技術記憶體
- 系統運維 SysOM profiling 在雲上環境的應用觀測實踐 | 龍蜥技術運維
- 龍蜥開源核心追蹤利器 Surftrace:協議包解析效率提升 10 倍! | 龍蜥技術協議
- 技術門檻高?來看 Intel 機密計算技術在龍蜥社群的實踐 | 龍蜥技術Intel
- 全面升級!龍蜥自動化運維平臺 SysOM 2.0 可支援作業系統一站式遷移 | 龍蜥技術運維作業系統
- 技術分享:記憶體管理記憶體
- 效能提升 57% ,SMC-R 透明加速 TCP 實戰解析 | 龍蜥技術TCP
- Inspur KOS 龍蜥衍生版面向智慧新媒體轉型的探索與實踐 | 龍蜥案例
- 空間都去哪裡了?(中)
- 跨語言程式設計的探索 | 龍蜥技術程式設計
- 助力Koordinator雲原生單機混部,龍蜥混部技術提升CPU利用率達60%|龍蜥技術
- 如何保證 Java 應用安全?標準答案來了 | 龍蜥技術Java
- SysAK 應用抖動診斷篇—— eBPF又立功了! | 龍蜥技術eBPF
- “時間”都去哪兒了?效能調優分析方法與案例詳解
- 萬里資料庫加入龍蜥社群,打造基於“龍蜥+GreatSQL”的開源技術底座資料庫SQL
- 龍蜥利器:系統運維工具 SysAK的雲上應用效能診斷 | 龍蜥技術運維
- 乾貨演講!龍蜥自動化運維平臺 SysOM 2.0 排程、記憶體相關診斷功能介紹 | 第 70-71 期運維記憶體
- 記憶體技術詞彙表記憶體
- 老程式設計師都去哪了?程式設計師
- eBPF 雙子座:天使 or 惡魔?| 龍蜥技術eBPF
- 龍蜥社群高效能儲存技術 SIG 11 月運營回顧 | 龍蜥 SIG
- 龍蜥開源Plugsched:首次實現 Linux kernel 排程器熱升級 | 龍蜥技術Linux
- 軟體調優方法有哪些?看看飛騰技術專家怎麼說 | 龍蜥技術
- 深入解讀基礎軟體雲原生面臨的挑戰 | 龍蜥技術
- Everspin MRAM記憶體技術如何工作記憶體
- linux kernel記憶體碎片防治技術Linux記憶體
- 老程式設計師都去哪兒了?程式設計師
- 35歲沒有晉級的同事都去哪了?
- MySQL 中刪除的資料都去哪兒了?MySql
- 載入速度提升 15%,關於 Python 啟動加速探索與實踐的解析 | 龍蜥技術Python
- Linux記憶體被吃掉了,它去哪裡了?Linux記憶體
- [譯].Net中的記憶體-什麼分配在了哪裡記憶體
- 議題解析與復現--《Java記憶體攻擊技術漫談》(一)Java記憶體