1. 程式人生 > >Lnmp的運維追蹤技巧總結

Lnmp的運維追蹤技巧總結

LNMP的運維追蹤技巧總結

曾幾何時我開始運維公司的LNMP網站,經過一段時間的摸爬滾打,也算是總結了不少在LNMP伺服器下除錯追蹤各種網站錯誤的方法。好記性不如爛筆頭,還是總結一下吧!

在開始我會梳理一下我所理解的一個web請求從發起到響應的各個階段伺服器和瀏覽器分別做了什麼。所以的使用者響應異常都是發生在這個流程中的,知道每個流程的細節可以通過不同的方法分別定位異常發生在哪個階段,從而更準確快速的定位錯誤。後面就是持續更新的我在被這個網站折磨中經歷的各種錯誤,給自己做一個記錄,當然如果能幫到其他人,我也很榮幸。

一個Web請求過程中到底發生了什麼?

簡單的web請求

上圖是一個簡單的web請求全過程,嗯,畫的確實有點過於簡單,上圖中我隱藏了很多細節,下面一一說明,可能有沒涉及到的地方歡迎補充:

第一步

使用者輸入url如http:www.baidu.com到瀏覽器,瀏覽器如chrom需要將其解析為ip地址才知道需要到哪裡去訪問哪個伺服器。瀏覽器解析DNS步驟如下:

  1. 搜尋瀏覽器自身的dns快取,這個快取快取時間短,快取數目有限。
  2. 搜尋作業系統的dns快取
  3. 讀取host檔案的dns對映(一般做本地開發對映都是修改這個檔案來達到攔截瀏覽器請求到本地伺服器的目的,從而使本地可以成功對映伺服器地址)
  4. 先本地網絡卡配置裡的dns伺服器發起域名解析請求,這裡好像還有一套運營商的處理流程就不在展開了。
  5. 下面好像還有一些流程,由於基本不會執行到這一步,一般所以dns運營商的dns伺服器都會搞定的。
  6. 解析失敗,以上任何一步成功都會返回一個成功的ip地址

第二步

瀏覽器以一個隨機的埠享這個ip地址的特定埠(預設80)發起著名的TCP3次握手。關於一個http請求是如何到達nginx服務的流程大致如下:

Created with Raphaël 2.1.2TCP請求進入網絡卡?核心的TCP/IP協議棧?防火牆?Nginx模組異常yesnoyesnoyesno

第三步

握手完成後的瀏覽器和伺服器就可以愉快地傳送http請求了,具體在nginx上流程如下:

Created with Raphaël 2.1.2http請求第二步流程 nginx程序 獲取http的頭部資訊
匹配server_name,定位到站點的root 進入程式碼框架的路由 框架的路由解析器解析出php檔案 php進入fastcgi程序 fastcgi程序將php填充成html檔案 html檔案遞交給nginx並設定響應資訊 response響應

第四步

瀏覽器根據伺服器resopnse的響應頭和響應體渲染出視覺化頁面

響應碼 說明
1xx 資訊性狀態說明
2xx 成功狀態碼
3xx 重定向狀態碼
301 永久重定向, Location響應首部的值仍為當前URL,因此為隱藏重定向
302 臨時重定向,顯式重定向, Location響應首部的值為新的URL
304 Not Modified 未修改,比如本地快取的資原始檔和伺服器上比較時,發現並沒有修改,伺服器返回一個304狀態碼,告訴瀏覽器,你不用請求該資源,直接使用本地的資源即可
4xx 客戶端錯誤
404 Not Found 請求的URL資源並不存在
5xx 伺服器錯誤
500 Internal Server Error 伺服器內部錯誤
502 Bad Gateway 前面代理伺服器聯絡不到後端的伺服器時出現
504 Gateway Timeout 這個是代理能聯絡到後端的伺服器,但是後端的伺服器在規定的時間內沒有給代理伺服器響應

上面大致梳理了下一個http請求在LNMP服務端體系下的流程。心中有個整體流程的概念才可以更好的追蹤實際問題。下面就是針對上面幾個基本步驟中會出現的問題的定位和追蹤。

第一步和第二步出現問題,可以通過「埠可用性探測」來定位。


  1. ping www.baidu.com 檢測域名解析器是否異常
檢查域名解析是否錯誤
  • telnet 127.0.0.1 80 追蹤埠是否異常
    檢查埠是否開啟,防火牆是否過濾
  • 第三步出現的問題

    這一步一般是網站出問題的主要地方,絕大部分問題都是出現在這個階段,同樣這個階段出現的問題也是最難定位和解決的。為了更好的處理這個階段的問題我們需要更深入地瞭解下一個web伺服器與一個web程式直接的資訊通訊的模型與流程。

    要說明這個問題,首先我們需要了解什麼是大名頂頂的CGI協議、FASTCGI協議和PHP-FPM,以及它們之前的關係。

    對於一個PHP的web程式來說,web伺服器(如:nginx)要想與它通訊需要通過CGI協議。當一個web請求觸達web伺服器時,web伺服器會建立一個CGI程序,CGI程序將web的請求按照固定的格式進行解析,然後寫入標準輸入(STDIN)和環境變數中,然後PHP啟動的CGI解析器會從標準輸入(STDIN)和環境變數中讀取http請求的資料,所以$_SERVER才會有資料,然後做出相應的邏輯處理,然後將處理結果放入標準輸出(STDOUT),CGI程序從STDOUT中讀取響應資料然後傳輸給瀏覽器,這樣服務端就完成了一次http請求。

    上面是CGI的實現流程,但是使用CGI協議的伺服器在使用者每次訪問伺服器的時候都需要fork/銷燬CGI程序,必然照成多餘的系統開銷,所以FASTCGI就是為了解決這個問題的。

    FastCGI會建立一個常駐的master程序和多個worker程序,master程序負責管理和為worker程序反派任務,worker程序負責內部嵌入了CGI解析器用於解釋php程式碼。

    PHP-FPM是一個FastCGI程序管理器,在LNMP體系中就是由它來實現FastCGI協議的。同樣,它也會建立一個常駐的master程序和多個worker程序,master程序負責監聽埠和接收來自nginx的請求,指派任務給worker程序。worker程序的負責解釋php程式碼。PHP-FPM可以通過配置預先啟動一定數量的worker程序,這樣當http請求觸達時就可以更快速的響應。

    nginx與PHP-FPM之間的通訊一般通過其ngx_http_fastcgi_module模組來實現。其中fastcgi_pass用於設定fastcgi伺服器的IP地址;fastcgi_param設定傳入fastcgi伺服器的引數。這個模組出現的配置問題一般集中在這一塊。

    相對於併發狀態下出現的問題,一般也都集中在fastcgi伺服器上,具體表現為fastcgi伺服器為了應對大量的http請求必須不停的fork新的worker程序,這時就需要考慮伺服器可支援的最大連結數和最大開啟檔案數(可通過ulimit -n檢視)以及php-fpm配置裡的最低開啟worker數和最高開啟worker數的限制。高效能伺服器可以在這個方向上調優。這也是我目前還在探索的地方,以後肯定也會寫一個總結。

    第四步出現的問題

    這一步一般很少出現問題,出現問題也很容易定位,多是前端渲染問題,我也不是很懂。

    未完分割線,後面我會總結一些各個階段可能發生的錯誤,這些錯誤在客戶端的表現,如何定位,以及如何解決。

    參考連結