摘要:是由淘寶網發起的服務器項目。回源監控是內容分發網絡的簡稱,其分發的內容來自用戶源站,負責回源的模塊是最重要組成部分之一,使跨越單機的限制,完成網絡數據的接收處理和轉發。這部分主要介紹的一些調試技巧和回源資源監控的內容,以及相應的實例分享。
摘要: Tengine是由淘寶網發起的Web服務器項目。它在Nginx的基礎上,針對大訪問量網站的需求,提供更強大的流量負載均衡能力、全站HTTPS服務、安全防攻擊、鏈路追蹤等眾多高級特性。團隊的核心成員來自于淘寶、搜狗等互聯網企業,從2011年12月開始,Tengine成為一個開源項目,團隊在積極地開發和維護著它,最終目標是打造一個高效、穩定、安全、易用的Web平臺。
Tengine是由淘寶網發起的Web服務器項目。它在Nginx的基礎上,針對大訪問量網站的需求,提供更強大的流量負載均衡能力、全站HTTPS服務、安全防攻擊、鏈路追蹤等眾多高級特性。團隊的核心成員來自于淘寶、搜狗等互聯網企業,從2011年12月開始,Tengine成為一個開源項目,團隊在積極地開發和維護著它,最終目標是打造一個高效、穩定、安全、易用的Web平臺。
阿里云CDN現在服務超過24萬家客戶,Tengine作為接入層提供高性能Web Server服務,是CDN系統最核心的組件之一。無論是來自阿里集團內部還是外部客戶的流量服務,幾乎都是由Tengine承載。可以毫不夸張地說,Tengine的服務質量直接影響著國內外無數大中小型Web站點的服務質量和業務存活,所以,維護Tengine的穩定性一直是我們團隊的最高優先級目標之一。經過了多年淘寶、天貓等大型網站雙十一活動的洗禮,Tengine的性能和穩定性已經得到了很好的驗證。
有一句俗語:“上帝說要有光,于是便有了光。“阿里云高級開發工程師墨飏說,“Tengine在做工具化的時候,也基本沿襲了這樣的思路。在做開發之前,我們會系統性地思考:我們需要面對什么樣的場景,會碰到什么樣的問題,需要怎樣的調試技巧和工具,是否可以解決更多此類問題,于是,我們的工具便會在這樣的思路下逐漸成型和完善。同時,在服務客戶的過程中,我們也會遇到各種新場景新問題,為了定位和解決問題,我們也會針對性地提出解決方案,沉淀出更多調試技巧和工具。作為一線開發團隊,我們一路走來積累了非常多調試技巧、工具化的經驗。”
本文由阿里云CDN團隊的研發同學笑臣和墨飏帶來,從Tengine的內存調試、核心結構、upstream、coredump四個部分展開,為大家整理和分享一些實踐經驗。
內存調試——精準定位問題
Tengine作為C語言開發的應用,在內存的使用中會碰到一些問題,第一部分將重點介紹內存調試方面的相關內容。
從下圖可以清晰的看出,Tengine內存分布可以從三個維度來理解:底層實現、抽象層、應用層。
一、底層實現
Tengine底層實現依賴操作系統的內存分配機制,常見的內存分配器包括jemalloc(FreeBSD)、ptmalloc(glic)、tcmalloc(Google),luajit則使用內置的dlmalloc庫。Tengine在每個連接accept后會malloc一塊內存,作為整個連接生命周期內的內存池, 當HTTP請求到達的時候,又會malloc一塊當前請求階段的內存池, 因此對malloc的分配速度有一定的依賴關系。jemalloc的性能是ptmalloc的兩倍以上,我們在使用Tengine的時候默認采用jemalloc。jemalloc在追蹤實際內存分配時可以使用“malloc_stats_print”來查看內部細節,幫助定位內存泄露等問題。
二、nginx pool調試
在底層內存分配工具無法定位問題時,我們需要從抽象層分析出了什么問題。
Tengine作為nginx 的fork,在使用nginx pool方面與官方nginx基本沒什么區別,它的內存池管理機制在HTTP請求的任一階段都可能被調用來分配內存,我們可以從內存分配的真實函數調用來統計內存分配的占用量、歷史數量、當前數量、large alloc等。mod_debug_pool已經在Tengine社區開源,有興趣可以自行查閱文檔,它的原理是通過hook ngx_create_pool函數來記錄__func__/__LINE__,在需要排查問題時可以展示歷史數據,從抽象層定位內存泄露等問題。
三、lua內存統計
lua/luajit是另一個非常成熟的開源項目,在nginx生態系統中,lua-nginx-module允許lua/luajit以虛擬機形式內嵌到nginx提供強大的腳本能力,我們在阿里云CDN海量業務開發中大量使用到lua/luajit。在調試luajit內存占用時,可以通過collectgarbage來展示總內存占用量,通過掃描gc object,可以統計global_State中所有gc對象,OpenResty社區也提供了GDB工具來輸出gc對象的數量和內存占用。
四、共享內存調試
Tengine是多進程服務模型,其進程間的通信主要依賴操作系統共享內存機制,隨著業務的發展共享內存的使用頻率越來越高,如何去定位、調試共享內存,是一個比較嚴峻的問題,且業內缺少相關工具。我們在調試共享內存問題時,沉淀和開源了mod_slab_stat工具,在Tengine社區可以查閱詳細的文檔,該工具統計和展示了每個zone的內存分配細節,包括page、slab和alloc num等,突出業務通信內容塊分布情況等。該工具適用于ngx shm,基于ngx slab的stub stats模塊是個例外。
以上,從底層實現、抽象層、應用層三個維度,可以定位到絕大部分Tengine系統和業務的內存問題,包括一些內存的調試技巧。
核心結構——調試與解決故障
Tengine作為高性能服務器被廣泛應用,它的核心框架和核心數據結構決定了其承載服務的質量。針對所遇到的CDN用戶上報故障的工單,比如請求異常、訪問慢等,如何從Tengine核心結構去調試、定位和解決問題,是本部分要介紹的內容。
Tengine主要的核心結構包括連接、請求和計時器等。連接承載著請求,以連接池的形式提供前端、后端網絡服務,其異步事件驅動的特性是Tengine高性能網絡服務的基石,而其事件模型又和計時器緊緊關聯,這些核心結構組成了Tengine的核心框架。
要調試和定位Tengine網絡問題,需要從連接、請求、計時器等多角度思考,從讀寫請求狀態、解析請求階段、應答輸出階段、建連等多維度采集,從而得到更詳細的全局監控數據。
Tengine在nginx stub status工具基礎上,開發了tsar工具(已開源),來展示更細粒度的歷史資源監控,包括應用層QPS、HTTPS和網絡層的accept、讀寫等待等。基于reqstatus的域名級監控,可以針對任意粒度域名級來統計請求數、連接數和5xx、4xx等狀態碼數量,還包括連接的復用情況等。
有了tsar和reqstatus工具,我們可以從全局來分析Tengine系統的服務和性能狀態,但是,這夠了么?CDN系統中,我們會遇到一些問題,比如:為啥tengine/nginx訪問慢?是因為客戶端慢、后端慢、還是nginx本身hang住?如何去衡量“慢“?我們需要對請求時間進一步細分。
Tengine新增了responsefirstbytetime、upstream_response_time、writewaittime、upstream_read_wait_time等變量來記錄從請求進入到響應結束整個請求流程中的包括不限于應答首字節、后端應答首字節、socket讀寫等待時間總和等關鍵指標。
Tengine在衡量和監控請求卡頓時,將events cycle內event平均處理時間和events cycle內timer平均處理時間綜合來定位單cycle平均耗時長的異常,常見的問題如同步IO(磁盤負載高時寫log卡頓)、CPU密集型執行流(lua實現的CPU密集型邏輯)。
有些時候,我們無法從全局資源監控角度定位問題,這時候可以從ngx_cycles->connections[]來查詢當前執行的請求或連接結構信息,通過gdb腳本來掃描worker內當前連接信息,查看和調試是否有請求堆積或連接泄露等問題。mod_debug_conn(待開源)工具是上述調試技巧的沉淀,它還可以幫助我們查看請求/連接的內存占用、分析連接和請求上的各類信息。
同時,Tengine的計時器(timer)在異步業務場景中有重要作用,通過掃描計時器紅黑樹,分析每個event timer,我們可以調試和定位異步操作中的問題。有時候我們在平滑升級tengine服務時,worker一直處于shutting down狀態無法退出,其實便是因為一直存在timer導致的。也可以通過hook ngx.timer.at函數來統計lua-nginx-module中的timer caller次數,解決timer超限的報錯等。
回源監控
CDN是內容分發網絡的簡稱,其分發的內容來自用戶源站,負責回源的upstream模塊是Tengine最重要組成部分之一,使Tengine跨越單機的限制,完成網絡數據的接收、處理和轉發。這部分主要介紹upsteam的一些調試技巧和回源資源監控的內容,以及相應的實例分享。
在上面的章節中,我們已經分析過如何依靠Tengine提供的關鍵指標來衡量和監控請求卡頓,那么,我們同樣可以提出問題:如何去分析請求代理或回源失敗?是因為客戶端主動斷連、后端異常還是請求超時?如何去分析真實的原因,從而實時監控回源失敗,這也是經常困擾CDN用戶和開發人員的難題。
從Tengine的請求處理流程分析,客戶端在完成TCP三次握手后,比較常見的錯誤是:1、客戶端異常斷開連接;2、客戶端主動斷開連接;3、等待讀寫客戶端超時。在Tengine讀取請求內容后,解析客戶端請求失敗如請求行/請求頭等協議出錯,在upstream模塊回源時,也可能發生連接后端失敗、后端異常斷開連接、后端主動斷開連接、等待讀寫后端超時、解析后端應答頭失敗等錯誤,我們可以從Tengine的錯誤日志查看對應的報錯信息,在此基礎上,我們從ngx_http_upstream_connect、ngx_http_upstream_send_request、ngx_http_upstream_process_header、ngx_http_upstream_process_body_in_memory等回源關鍵函數切入,提供error flag來監控真實的客戶端/回源失敗原因,將錯誤統計輸出至訪問日志、reqstatus工具等,關聯和分析域名/請求級別的回源失敗問題,保障CDN服務的穩定性。
現在,我們有了回源的關鍵指標變量和error flag,可以依靠一些調試技巧來分享一個upstream問題實例。如圖所示,當客戶端請求通過Tengine upstream回源時,我們可能碰到這樣的問題:
讀源站,讀滿buffer
發送buffer size數據給客戶端,全發完了
循環上述兩步驟…
繼續讀源站,讀出若干數據,且源站已讀完
發送部分給客戶端,未發完(客戶端卡或者其他原因)
再次讀upstream,讀出again(顯然,因為之前源站數據讀完了)
繼續發送數據給客戶端,未發完(客戶端卡或者其他原因)
upstream回源先超時了,這個時候$error_flag表明等待讀源站超時,但是事實是這樣嗎?
我們提供了完整的復現方法,如圖所示:
站在上帝視角,很明顯可以看到其實是客戶端問題,但是回源采集的關鍵指標:errorflag、upstream_read_wait_time、$write_wait_time,卻告訴我們是源站出錯導致的問題,數據不會欺騙我們,那么問題到底在哪里?
上述調試的一些技巧和回源監控,幫助我們理解upstream模塊的原理:
1、upstream有2個計時器,前端的和后端的;
2、Tengine/Nginx即使寫客戶端寫不進去,只要proxy buf沒滿也會嘗試讀后端,如果后端數據讀完了,會讀出EAGAIN;
3、后端計時器較短先超時了,關閉請求,此時往往認為后端出錯,真實情況是客戶端出錯;
這個特殊實例,在某些場景下,甚至在很多的生成環境中,都是比較常見但卻往往被忽視的問題,在幫助提升用戶體驗和服務質量的目標下,即使是nginx核心代碼不易發現的bug,在完善的調試工具和回源監控下,一樣無所遁形。有興趣的同學可以搜索nginx郵件列表來詳細了解問題背景,雖然nginx 官方因為一些原因沒有合入該patch,我們在Tengine中也做了多帶帶的優化策略。
Coredump
coredump是Tengine這類C開發的應用程序比較常見的問題,隨著業務的迅猛發展,coredump往往會變得越來越大,甚至越來越頻繁,我們從空間、數量、自動分析等角度層層遞進來優化Tengine的coredump。
“cat /proc/PID/coredump_filter”這行指令幫助我們了解Linux操作系統coredump機制所支持的內存形態,包括私有內存、共享內存等。我們在使用Tengine時可以去除共享內存,降低coredump文件大小。同時,也可以限制一定時間內crash寫coredump文件的次數,防止磁盤IO過高或磁盤空間被占滿,Tengine提供了“worker_core_limit”指令(待開源)來限制至分鐘/小時/天級別。
現在我們已經從空間和數量角度優化了coredump,方便了調試。那么是否可以自動化完成分析,提升定位問題的速度?答案是肯定的。
我們通過gdb python腳本來自動分析coredump文件,從中提取得到觸發問題的請求的host、URL、headers等,有了這些信息,就可以不斷復現來快速調試和定位問題。但是有時候,coredump棧并不能告訴我們完整的現場,而在crash時,Tengine丟失了日志中的請求信息,我們將這些信息記錄在環形內存中,通過coredump文件將環形緩沖數據輸出到文件,環環相扣,完整的現場,真相只有一個。
原理:http://nginx.org/en/docs/ngx_...
事后諸葛只能查漏補缺,我們需要提前發現問題,實時流量拷貝工具應運而生。http_copy是Tengine的擴展模塊,可以實時放大轉發本機的流量(HTTP請求),可以配置放大流量到指定地址和端口,也可設置放大的倍數和并發量等,更可以通過源站健康檢查來自動關停流量,避免過大流量對Tengine和源站的正常服務造成影響。
在流量壓測/流量拷貝時,不需要真實返回響應的內容,減少帶寬消耗,drop_traffic工具添加body filter直接丟棄數據,或者截獲c->send_chain/c->send函數直接丟棄數據,在調試時發現問題而不產生問題。
以上就是阿里云CDN團隊對于Tengine的內存調試與資源監控方面的一些實踐經驗,希望對于正在使用開源Tengine的同學有一些幫助。
Tengine官網:http://tengine.taobao.org
Tengine Github:https://github.com/alibaba/te...
阿里云CDN:https://www.aliyun.com/produc...
最后,阿里云CDN團隊正在招聘志同道合的伙伴,歡迎加入~
原文鏈接
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/8046.html
摘要:今天分享的主題是阿里七層流量入口硬件加速探索之路。業務驅動了技術創新,年接入層在硬件加速領域邁出了第一步。三監控,對硬件加速相關的資源指標進行實時監控和報警,防患于未然。硬件加速效果上線后我們獲得了一些加速效果的數據。 摘要: Tengine在軟件層面已經有了深度的調試和優化經驗,但是在硬件層面,通用處理器(CPU)已經進入了摩爾定律,有了瓶頸。而在業務量突飛猛進的當下,如何利用硬件來...
摘要:淘寶定制基于,是國內第一個優化定制且開源的服務器版虛擬機。數據庫開源數據庫是基于官方版本的一個分支,由阿里云數據庫團隊維護,目前也應用于阿里巴巴集團業務以及阿里云數據庫服務。淘寶服務器是由淘寶網發起的服務器項目。 Java JAVA 研發框架 SOFAStack SOFAStack(Scalable Open Financial Architecture Stack)是用于快速構建金融...
摘要:內容主要有四個方面趨勢基礎實踐調試。一趨勢這一章節主要介紹近幾年和未來的趨勢,包括兩大瀏覽器和對的態度,以及淘寶天貓和阿里云的實踐情況。完整性是指為了避免網絡中傳輸的數據被非法篡改,使用算法來保證消息的完整性。 摘要: 本文邀請阿里云CDN HTTPS技術專家金九,分享Tengine的一些HTTPS實踐經驗。內容主要有四個方面:HTTPS趨勢、HTTPS基礎、HTTPS實踐、HTTPS...
閱讀 823·2021-09-07 09:58
閱讀 2681·2021-08-31 09:42
閱讀 2854·2019-08-30 14:18
閱讀 3086·2019-08-30 14:08
閱讀 1831·2019-08-30 12:57
閱讀 2757·2019-08-26 13:31
閱讀 1298·2019-08-26 11:58
閱讀 1052·2019-08-23 18:06