服務器排障 之 nginx 499 錯誤的解決

問題描述:python

Nginx 服務器大量499報錯mysql

220.181.165.136 - - [18/May/2015:10:31:02 +0800] "POST /v1/jobsHTTP/1.1" 499 0 "" "bdHttpRequest/1.0.0"
 
115.239.212.7 - - [18/May/2015:10:31:03 +0800] "GET /v1/job/643309e3-dc73-4025-aa69-c9405c1d818fHTTP/1.1" 499 0"http://www.baidu.com/?tn=91638679_hao_pg&s_j=1""Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko"
 
140.207.202.187 - - [18/May/2015:10:30:58 +0800] "POST/v3/violations HTTP/1.1" 499 0 "-" "-"
 
42.236.10.71 - - [18/May/2015:10:30:59 +0800] "POST /v3/violationsHTTP/1.1" 499 0 "-" "-"
 
106.120.173.17 - - [18/May/2015:10:30:58 +0800] "POST/v3/violations HTTP/1.1" 499 0 "-" "Mozilla/5.0 (Windows NT6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131Safari/537.36"
 
180.97.35.164 - - [18/May/2015:10:30:52 +0800] "GET/v1/job/f86bdecc-2a61-4a42-bb7b-aa794b77f89b HTTP/1.1" 499 0"http://www.baidu.com/s?word=%E5%8D%81%E5%A0%B0%E5%A4%A9%E6%B0%94&tn=sitehao123&ie=utf-8""Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"

問題分析:nginx

1  499出現的緣由sql

google定義:數據庫

499 / ClientClosed Request後端

    An Nginx HTTP server extension. This codeis introduced to log the case when the connection is closed by client whileHTTP server is processing its request, making server unable to send the HTTP header backapi

維基百科定義:緩存

499Client Closed Request (Nginx)bash

Used in Nginx logs to indicate when the connection has been closed by client while the server is still processing itsrequest, making server unable to send a status code back服務器

Nginx源碼:

grep一下nginx源碼,定義在ngx_request_t.h :

/*
* HTTP does notdefine the code for the case when a client closed
* the connectionwhile we are processing its request so we introduce
* own code to logsuch situation when a client has closed the connection
* before we even tryto send the HTTP header to it
*/
#define NGX_HTTP_CLIENT_CLOSED_REQUEST 499

這是nginx定義的一個狀態碼,用於表示這樣的錯誤:服務器返回http頭以前,客戶端就提早關閉了http鏈接

繼續grep :

wKioL1ZK_oWDZn9NAAC_HrhuQAs422.png


頗有多是由於服務器端處理的時間過長,客戶端不耐煩

要解決此問題,就須要在程序上面作些優化了。

 

再grep下「NGX_HTTP_CLIENT_CLOSED_REQUEST」,發現目前這個狀態值只在ngx_upstream中賦值


upstream在如下幾種狀況下會返回499:

(1)upstream 在收到讀寫事件處理以前時,會檢查鏈接是否可用:
ngx_http_upstream_check_broken_connection,
    if (c->error) { //connecttion錯誤
     ……
        if (!u->cacheable) { //upstream的cacheable爲false,這個值跟http_cache模塊的設置有關。指示內容是否緩存。
            ngx_http_upstream_finalize_request(r, u, NGX_HTTP_CLIENT_CLOSED_REQUEST);
        }
}

如上代碼,當鏈接錯誤時會返回499。

(2)server處理請求未結束,而client提早關閉了鏈接,此時也會返回499。

(3)在一個upstream出錯,執行next_upstream時也會判斷鏈接是否可用,不可用則返回499。

總之,這個錯誤的比例升高可能代表服務器upstream處理過慢,致使用戶提早關閉鏈接。而正常狀況下有一個小比例是正常的。

繼續分析:

問題的核心就是要排查爲何服務端處理時間過長

可能問題

1      後臺python程序處理請求時間過長

2      mysql慢查詢

經過查看監控:

1  cpu和內存的使用,都在正常範圍

2  後臺程序訪問正常

3  MySQL沒有慢查詢


結果:

通過詢問老大後得知,這個nginx爲查詢違章的api,用戶提交查詢後, python就去數據庫或者交通局的網站查詢。這個查詢會有消耗必定的時間,因此,用戶會主動斷開鏈接

解決問題:

proxy_ignore_client_abort  on;  #讓代理服務端不要主動關閉客戶端的鏈接。

 

默認 proxy_ignore_client_abort 是關閉的,此時在請求過程當中若是客戶端端主動關閉請求或者客戶端網絡斷掉,那麼 Nginx 會記錄 499,同時 request_time 「後端已經處理」的時間,而upstream_response_time - (已驗證)

 

若是使用了 proxy_ignore_client_abort on ;

那麼客戶端主動斷掉鏈接以後,Nginx 會等待後端處理完(或者超時),而後記錄「後端的返回信息」到日誌。因此,若是後端返回 200就記錄 200 ;若是後端放回 5XX ,那麼就記錄 5XX

若是超時(默認60s,能夠用 proxy_read_timeout 設置)Nginx 會主動斷開鏈接,記錄 504

注:只在作反向代理的時候加入,做爲其餘服務器的時候,關閉爲好,默認設置是關閉的!

相關文章
相關標籤/搜索