Nginx效能優化

發表於2015-08-12

Nginx作為一個非常流行和成熟的Web Server和Reserve Proxy Server,網上有大量的效能優化教程,但是不同的業務場景千差萬別,什麼配置是最適合自己的,需要大量的測試和實踐以及不斷的優化改進。最近使用者呼叫量突破百萬大關之後,就遇到了一些問題,雖然不算太複雜,但也折騰了挺長時間才搞定,積累了不少經驗。

碰到的這個問題其實已經有一段時間了,有客戶給我們反饋呼叫超時,但是我們自己從系統監控上看都是正常的,只有幾十毫秒肯定不會超時,懷疑是不是網路的原因,但是出現幾次後,就隱隱感覺這個問題可能不是偶發性的,應該還有深層次的原因。

因為我們服務面向企業客戶的,雖然每家客戶的呼叫量可能會非常大,但每家企業客戶就那麼幾個公網IP,即使以後有上千家客戶,Nginx也可以輕鬆支撐這些併發連線。因此,首先先從網路上對Nginx長連線作了優化,將長連線從原來配置的5秒鐘改成5分鐘,將每次建立連線請求的數目從預設的100調整到1000。

調整完畢後,通過netstat -anp命令可以看到,新建連線請求會減少,說明長連線已起到作用。但過了一段時間,仍然發現有客戶呼叫超時的情況發生,從Nginx日誌中可以看到請求時間還是有超過1s的,甚至有長達20s左右的,如下所示:

檢視原圖

並且從Zabbix上的監控發現一個現象,當connection writing或active數突然增高時,請求時間就相應的出現較多超時:

檢視原圖

檢視應用的日誌,發現執行時間並不長:

檢視原圖

應用程式裡統計的時間,只是從業務開始執行到執行結果的時間,這個還沒有算Tomcat容器的執行時間,外部請求的執行路徑如下:

會不會是Tomcat容器本身執行有問題呢,把Tomcat請求的日誌呼叫出來,發現這個時間點前後的執行也是正常的:

從請求路徑上分析,肯定是Nginx到Tomcat這層存在一些問題。正在排查這個問題的時候,突然發現有大量30s左右的超時,從Zabbix上也觀察到connection writing非常高,如下所示:

檢視大圖

同時,發現TIME_WAIT的連線特別多,從現象及抓包分析結果來看,應該是有客戶沒有開啟長連線,而我們在服務端又設定了keepalive_timeout為5分鐘,導致大量使用過的連線等待超時,當時有接近2000個,編輯/etc/sysctl.conf檔案,增加如下兩個引數重用連線:

生效之後很快下降到200以下,從Zabbix監控上也看到,connection writing和connection active`都有明顯下降,但並沒有完全解決問題,還得找其它方面的原因。

檢視大圖

Nginx的reqeust_time指的是從客戶端接收到第一個位元組算起,到呼叫後端的upstream server完成業務邏輯處理,並將返回結果全部寫回到客戶端為止的時間,那麼呼叫upstream server的時間如果能夠列印出來的話,就更容易將問題範圍縮小,幸運的是Nginx有兩個引數可以列印後端伺服器請求的時間和IP地址,在nginx.conf檔案中修改日誌的格式如下:

再觀察日誌,非常明顯地發現,大部分特別長的呼叫都來自同一臺機器:

檢視大圖

檢視這臺機器發現,雖然Java程式還在,但應用實際上已經當掉了,沒有真實的請求進來,將之從負載勻衡中摘掉,問題馬上得到緩解:

檢視大圖

這臺機器其實已經掛掉了,但為何Nginx沒有識別到呢?進一步研究發現,Nginx在呼叫upstream server時,超時時間預設是60s,我們這些應用對響應時間要求非常高,超過1s已沒有意義,因此在nginx.conf檔案中修改預設的超時時間,超過1s就返回:

執行一段時間後,問題已基本得到解決,不過還是會發現request_time超過1s達到5s的,但upstream_response_time都沒有超時了,說明上面的引數已起作用,根據我的理解,request_time比較長的原因可能跟客戶那邊接收慢有關係,不過這個問題最終還需要下週等客戶改為長連線才能確認。

相關文章