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