Nginx

Mr. Time To First Byte 的怪事

  • April 7, 2016

我有一個基於 Linode 1024 VPS 的網路伺服器

  • Ubuntu 11.10
  • Nginx 1.0.5
  • PHP 5.3.6(帶有 PHP-FPM、APC)
  • 清漆 3.0.2

還有一些基於 WordPress 3.3.1 的部落格。其中之一是一個普通的部落格,帶有預設配置、主題和“Hello World”文章,用於測試伺服器。另一個是從其他伺服器複製的部落格,有近 1 萬條文章和超過 1 萬條評論。這個部落格每天有大約 5k 個獨立使用者。

伺服器在測試部落格的 ab 測試中給出了很好的數字,但是用複製的部落格進行相同的測試是不可能的:ab 測試載入伺服器太多,我必須停止該過程,這無論如何都會使 ab 顯示這真是糟糕的結果

htop 在正常執行時也顯示“正常”負載,但在 ab 測試期間顯示異常大負載。

發生了另一件奇怪的事情(對我來說最重要):第一個字節的時間非常高,但在那之後等待站點載入非常快。這可以很容易地使用 tools.pingdom.com 等服務進行測試,它給出了這個結果。請注意表示“等待時間”的黃色區域。

為什麼會這樣?可能的想法:

  • 錯誤的 PHP-FPM 配置
  • Linode DNS 響應時間很糟糕。廢話-測試部落格解析DNS很好,TTFB很棒
  • 錯誤的 Nginx 配置

如果有人需要更多資訊,

首先,這不是一個答案,而是一種診斷方法。

這絕不是全面的——甚至是接近的,這只是一個起點。

第一個字節的時間

到第一個字節的時間 (TTFB) 有許多組成部分:

  • DNS查找:查找域的IP地址(可能的改進:更多/分佈式/響應式DNS伺服器)
  • 連接時間:打開一個到伺服器的套接字,協商連接(典型值應該在“ping”時間左右——通常需要往返——keepalive 應該有助於後續請求)
  • 等待:在發送第一個字節之前需要進行初始處理(這是您應該改進的地方 - 這對於動態內容最重要。

當您查看 ApacheBench 輸出時,您還會看到:

  • 處理:這是等待 + 完整傳輸內容的總和(如果傳輸時間明顯長於預期下載接收到的數據量,則正在進行進一步處理(在接收到第一個字節之後)(例如,頁面是在可用時刷新內容)

消除組件的比較

除了少數例外,您的問題將在於後端處理,這通常歸結為過於復雜/效率低下的程式碼,或配置不當的 MySQL。

解決此問題的一個好方法是通過一系列比較來消除設置的各個方面。一個好的比較應該盡可能保持不變,以幫助縮小問題範圍。目前,您提供了以下比較:

  1. 在舊伺服器和新伺服器上執行的相同(複製)站點:
  • 區別:伺服器
  • 結果:舊伺服器很快;新伺服器很慢
  • 注意:這裡你需要量化這些伺服器之間的差異——無論是在所使用的堆棧(Nginx 等)和硬體方面(舊伺服器是否更快,因為它是一台更強大的機器?)
  • 結論:程式碼可能能夠在正確的設置下快速執行
  1. 新伺服器上的測試站點與完整站點
  • 區別:內容、主題、外掛等
  • 結果:測試站點很快,整個站點很慢
  • 注意:理論上,這個測試應該可以幫助你消除設置的很多方面——DNS、網路,甚至你的 nginx/php/mysql 設置——但是,它並不是很“公平”。
  • 結論:額外內容對性能有顯著影響

理想的測試是讓您複製整個站點,然後刪除除一篇文章和相關評論之外的所有內容。該測試的目的是最終確定是否大量內容是問題所在,或者您的設置的其他方面(wordpress 外掛、主題等)是否是原因。您基本上會比較相同站點在同一(新)伺服器上的性能 - 載入相同的頁面(相同的長度等) - 唯一的區別是總站點內容(例如,某些外掛很有可能沒有隨著內容的增加可以很好地擴展)。

在不更改任何內容的情況下,您可以進行其他一些比較:

  • 從遠端位置與本地測試 - 這將有助於確定網路、延遲、dns 等是否是原因

    • 您已經(在某種程度上)完成了這項工作,並且大多數情況下得出的結論是您沒有網路問題。
  • 通過 Varnish(即埠 80)與 nginx 直接(埠 8080)進行測試 - 盡量不要在測試之間更改配置 - 只需使用正確的埠即可。這將向您展示 Varnish 的影響。由於 Varnish 是一個記憶體層,它應該非常快速地處理第一個請求之後的所有請求 - 本質上,它應該繞過後端和生成動態頁面所需的處理,並非常快速地提供記憶體副本。

    • 您已經這樣做了(儘管不是在本地),並證明了 Varnish 對您的表現有顯著的積極影響。

調整你的後端

至此,您應該已經發現了問題,或者得出結論認為問題出在您的後端。剩下的就是 Nginx、PHP 或 MySQL。

(我應該在這裡提一下,知道您的瓶頸是 CPU、RAM 還是 I/O 總是很方便 - 在sartopiostatvmstatfree等之間,您應該能夠對此得出一些結論。)

Nginx

Nginx 只是接受請求並提供靜態內容或將請求轉移到 PHP-FPM - Nginx 通常沒有太多可優化的地方。

  • 設置工作人員 = # CPU 核心
  • 啟用keepalive(10-15的值很好)
  • 禁用不需要的日誌記錄
  • 如果需要,增加緩衝區大小
  • 避免 if 語句(盡可能使用靜態名稱而不是正則表達式,消除不需要的擴展)

理想情況下,您的測試部落格和複製部落格具有相同的配置,在這種情況下,您已經有效地消除了 Nginx 的問題。

應用

如果您試圖辨識程式碼中的問題(例如慢速外掛等),慢速日誌是開始的地方。

  • 啟用 MySQL 慢日誌和 PHP-FPM 慢日誌執行你的基準測試,看看什麼是慢的。

MySQL

PHP

  • 禁用不需要的擴展,
  • 禁用 register_globals、magic_quotes_*、expose_php、register_argc_argv、always_populate_raw_post_data
  • 增加 memory_limit
  • open_basedir 和 safe_mode 具有顯著的性能影響,但也可以提供額外的防禦層。使用和不使用它們進行測試,以確定它們對性能的影響是否可以容忍。

PHP-FPM 程式碼

  • 調整 pm.* 值 - 增加它們以處理高負載

值得注意的是,您的 htop 結果顯示 php-fpm 消耗了大量 CPU - 您的問題似乎與此直接相關。

記憶體

優化每個可能的瓶頸後,開始記憶體。

  • 你已經有一個操作碼記憶體(APC)——確保它正常工作(它帶有一個測試文件)——檢查你的記憶體命中率,如果可能的話,將 APC 記憶體到記憶體而不是磁碟。
  • 將程式碼設置為記憶體(例如,使用 W3TC 等 Wordpress 外掛)
  • 使用 nginx,您可以設置 FastCGI 記憶體 - 但由於您有 Varnish,因此最好避免這樣做。
  • 設置一個記憶體層,例如 Varnish(您已經完成) - 並確保它正在工作(例如使用 varnishstat,閱讀Achieving a high Hitrate
  • 為站點的組件添加更多記憶體 - 例如 MemCached(如果適用)

有時,鑑於您的應用程序和硬體的限制,您可能無法大幅提高後端性能 - 然而,這就是記憶體的重點 - 以盡量減少後端的使用。

進一步閱讀

引用自:https://serverfault.com/questions/350062