記憶體減少 60%,OpenResty XRay 精準定位問題程式碼,快速完成修復上線
我們業務大規模的使用 OpenResty 相關生態,業務中偶爾出現過一些比較詭異的難以定位的問題, 比如記憶體、CPU 熱點等,藉助於 OpenResty XRay,我們能很快定位到根因並迅速解決這些問題。
OpenResty XRay部署簡單,對業務無侵入性,介面直觀清晰,對我們提供了很多最佳化的方向性指引, 已經成為我們的有力武器。
祝 OpenResty XRay 越來越好!
OpenResty XRay 是由 OpenResty Inc.1 研發的深度應用效能管理(APM)產品,以非侵入式的方式,對應用系統進行實時 X 光診斷與最佳化。今年上半年公開申請試用以來,已經成功的幫助到了不少的客戶,得到了客戶的廣泛好評。
上海雲盾資訊科技有限公司(YUNDUN),是專注於提供新一代安全產品和服務的創新創業企業。 在雲盾的產品線中,也有大規模使用開源 OpenResty,開源 OpenResty 的高效能以及靈活的定製能力,為雲盾的產品提供了強大的支援。同時,在使用開源 OpenResty 的過程中,也碰到了一些比較棘手的問題。
worker 程序記憶體佔用高
這是雲盾第一次使用 XRay 的場景,當時生產環境的 OpenResty worker 程序佔用的記憶體比預期的多,並且把流量切走之後記憶體也不會下降。當時排查了很久,初步定位是 LuaJIT 佔用記憶體多導致的,但是沒有辦法定位到更具體的問題點,希望 XRay 可以幫助分析診斷問題。
分析過程
首先直接在生產環境部署 XRay。是的,XRay 不需要應用程式的配合,以非侵入的方式來分析應用程式,可以直接應用於生產環境。
面對記憶體方面的問題,XRay 已經整合了一成套的分析方案,具體的背景知識可以參考這些博文:
我們首先關注 OpenResty worker 程序在應用層面的記憶體使用情況。
我們可以看到 Stream LuaJIT 佔用了大多數的記憶體,點選這個塊看細節。
我們可以看到大部分記憶體是由 stream 子系統的 LuaJIT GC 所管理的,點選這個塊繼續分析。
我們可以看到有上百萬個 table 物件,佔用了大部分的記憶體。我們繼續看 GC 物件引用關係火焰圖。
在 Lua 的世界裡,一個 Lua GC 物件如果有被 GC root 引用,那他就是“活著”的狀態,否則就是屬於 “死” 的狀態,隨著 GC 的工作,這個物件終將會被清理釋放掉。
GC 物件引用關係火焰圖,是把引用關係鏈以火焰圖的形式展示出來,從下往上表示引用關係,寬度表示記憶體佔用的大小。
具體到我們得到的火焰圖,此時我們可以看到 ngx.ctx
上引用的物件佔用了很多的記憶體,並且也很分散,我們選中火焰圖中一個柱子看:
此時可以看到是 ngx.ctx.game_conf.tcp
上引用了 66 個 table,佔用了 1MB+ 的記憶體,
選其他的柱子看了也都是類似的引用。
有了這個層面的關鍵資訊,雲盾的工程團隊也很快就完成了最佳化改進。
從開始使用 XRay,到分析定位問題,最佳化改進,最後到上線驗證確認有效,前後一共只有半天的時間。如果沒有 XRay 這種精準定位問題的能力,這是無法想象的。
我們再用 XRay 來看下最佳化後的真實情況,總體記憶體佔用降低了 60%+。
此時我們看到 Stream LuaJIT 佔用也不高了,比最佳化前下降了 80%+,最佳化工作已經順利完成。
worker 程序記憶體不釋放的疑問
不過此時還有一個疑問,為甚麼之前流量切走之後, 記憶體佔用也並沒有很明顯降低呢。 我們可以看下流量切走之後的分析,如下圖
我們可以看到 LuaJIT 記憶體分配器管理的記憶體中,大部分都是在空閒的記憶體池中,並沒有釋放給作業系統。 這是因為 LuaJIT 的記憶體分配器有空閒記憶體池機制,只有當出現連續的整段空閒記憶體,才會將記憶體釋放給作業系統。
我們還可以透過走勢圖,完整的看到記憶體使用變化的過程,比如下圖:
從記憶體走勢圖中可見,流量切走過程中, 正在使用的記憶體逐步減少,空閒的記憶體逐步降低, 在流量切回來的時候,空閒的記憶體又開始被使用起來了。撥雲見日,謎團解開。
-
OpenResty Inc. 是開源 OpenResty 專案建立者章亦春建立的商業公司。 ↩︎