深入剖析nginx
前面所講的除錯方法都是針對nginx本身很容易跑到的邏輯,而對於某些只有在特定情況下才會被執行到的**,又該怎樣去除錯呢?舉個例子,我們知道nginx裡有大量的超時處理,比如,如果讀取客戶端請求頭部資料超時,nginx就將執行對應的超時處理函式,假設我想通過單步執行的方式來了解這部分相關邏輯,無疑就得讓nginx的執行邏輯走到這條路徑上來。由於此時影響nginx行為的決定因素是客戶端所傳送的請求頭部資料,我們就必須在客戶端做動作來構造出這種場景。一般的瀏覽器,如ie、firefox等發出請求的行為基本已經固定,而常用的命令列工具,比如curl、wget的源**又略顯複雜,定製它們的請求動作和改變環境來構造所需的場景相對較為麻煩,所以一種更便利的方法就是我們自己寫個socket通訊的客戶端即可,而這並不需要多少**。
下面給出乙個測試示例用**,為了簡單,所以伺服器ip和埠都是固定在**裡的,用於傳送資料的函式write()呼叫也未做返回值判斷等(後續還有其他類似測試**也是如此,這點請注意)。
00: **片段2.6-1,檔名: request_timeout.c
48: }
該程式的**比較簡單,變數req_header儲存的是http請求頭部資料,被注釋掉的是正常的請求頭,而我這裡使用的請求頭是不完整的(正常請求頭可以用wget、curl或wireshark1等工具獲得,異常請求頭必須根據自己所預期場景來進行構造,比如在這裡,其他異常情況的請求頭可能導致nginx以其他錯誤方式返回而不是進行超時監控),所以這會使得nginx在接收到該請求後,持續等待進一步的頭部資料,直到超時。編譯這個源**得到應用程式request_timeout。
將接受http請求的nginx工作程序繫結到gdb,然後在超時函式ngx_event_expire_timers()內的第149行下斷點並按c繼續。
75: **片段2.6-2,檔名: ngx_event_timer.c
76: void
77: ngx_event_expire_timers(void)
78:
將執行到第976行的if判斷內部,即連線超時,我們看到對於在讀取請求頭部資料超時的情況下,nginx工作程序最後所做的幾步主要工作,即日誌記錄、關閉請求並返回。通過這樣乙個例項,我們也就了解了如何去除錯這樣的特殊應用邏輯,不僅僅只是針對客戶端,對於後端應用伺服器也能如此進行模擬構造。
上面演示的環境構造步驟,雖然比較簡單且能真實模擬,但畢竟需要我們了解它的細節,也就是需知道觸發這種情況的前提條件,如果前提條件比較多,那麼模擬起來可能還是比較麻煩,其實,如果我們只是了解一下nginx如果這樣執行會怎麼樣,那麼完全可以通過利用gdb的p命令或set命令修改對應條件變數的值來達到目的。比如在前面的例子裡,在一般情況下,rev->timedout為0,即不超時而無法執行第977-980行**,但我又想看一下執行這幾條語句的情況會怎麼樣,那麼就可以像下面這樣做。
(gdb)通過執行「p rev->timedout=1」把變數rev->timedout的值改為1,這樣就執行到第977行了,當然,如上所示,set命令也可以改變nginx執行變數的值。值得特別注意的是,這樣做僅僅只是因為改變了條件判斷的變數值而使得nginx程式執行路徑發生變化,但是其在新的路徑上,可能由於使用的某些變數值不是原本所期望的情況而導致執行異常。
《深入剖析Nginx》一1 1 主要特性
深入剖析nginx 作為輕量級http服務的典型代表,nginx除了具備體積小 配置靈活 併發能力強 穩定等眾所周知的特點以外,在官方 還詳細列出了nginx的一些主要特性,我們來詳細了解一下1。1 http服務基本特性 2 http服務高階特性 3 郵件 服務特性 4 架構和擴充套件性 5 已測試...
深入剖析nginx時間快取
本文適合對nginx實現原理比較感興趣的同學閱讀,需要具備一定的服務端程式設計知識。在伺服器開發領域,時間的準確度關係到系統能否正常執行,尤其是當系統中存在超時事件需要處理時。但是系統時間的獲取需要一次昂貴的系統呼叫,作為一款成熟的伺服器軟體,nginx是如何優化這部分的效能開銷?接觸過系統設計的同...
深入剖析Nginx時間快取
在伺服器開發領域,時間的準確度關係到系統能否正常執行,尤其是當系統中存在超時事件需要處理時。但是系統時間的獲取需要一次昂貴的系統呼叫,作為一款成熟的伺服器軟體,nginx是如何優化這部分的效能開銷?接觸過系統設計的同學都知道,對於頻繁的資料獲取,在資料未變化的情形下,可以通過增加快取來優化效能,因為...