最近了解下Nginx的Code狀態碼,在此簡單總結下。一個http請求處理流程:php
一個普通的http請求處理流程,如上圖所示:
A -> client端發起請求給nginx
B -> nginx處理後,將請求轉發到uwsgi,並等待結果
C -> uwsgi處理完請求後,返回數據給nginx
D -> nginx將處理結果返回給客戶端
每一個階段都會有一個預設的超時時間,因爲網絡、機器負載、代碼異常等等各類緣由,若是某個階段沒有在預期的時間內正常返回,就會致使此次請求異常,進而產生不一樣的狀態碼。html
1)504 錯誤
504主要是針對B、C階段。通常nginx配置中會有:node
location / { ... uwsgi_connect_timeout 6s; uwsgi_send_timeout 6s; uwsgi_read_timeout 10s; uwsgi_buffering on; uwsgi_buffers 80 16k; ... } 這個表明nginx與上游服務器(uwsgi)通訊的超時時間,也就是說,若是在這個時間內,uwsgi沒有響應,則認爲此次請求超時,返回504狀態碼。 具體的日誌以下: access_log [16/May/2016:22:11:38 +0800] 10.4.31.56 201605162211280100040310561523 15231401463407888908 10.*.*.* 127.0.0.1:8500 "GET /api/media_article_list/?count=10&source_type=0&status=all&from_time=0&item_id=0&flag=2&_=1463407896337 HTTP/1.1" 504 **.***.com **.**.**.39, **.**.**.60 10.000 10.000 "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36" ... error_log 2016/05/16 22:11:38 [error] 90674#0: *947302032 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 10.6.19.81, server: **.***.com, request: "GET /api/media_article_list/?count=10&source_type=0&status=all&from_time=0&item_id=0&flag=2&_=1463407896337 HTTP/1.1", upstream: "http://127.0.0.1:8500/**/**/api/media_article_list/?count=10&source_type=0&status=all&from_time=0&item_id=0&flag=2&_=1463407896337", host: "mp.toutiao.com", referrer: "https://**.***.com/articles/?source_type=0" error_log中upstream timed out (110: Connection timed out) while reading response header from upstream, 意思是說,在規定的時間內,沒有從header中拿到數據,即uwsgi沒有返回任何數據。
Nginx 504 Gateway Time-out的含義是所請求的網關沒有請求到,簡單來講就是沒有請求到能夠執行的PHP-CGI。Nginx 504 Gateway Time-out則是與nginx.conf的設置有關。504 Gateway Time-out問題常見於使用nginx做爲web server的服務器的網站。nginx
通常看來, 這種狀況多是因爲nginx默認的fastcgi進程響應的緩衝區過小形成的, 這將致使fastcgi進程被掛起, 若是你的fastcgi服務對這個掛起處理的很差, 那麼最後就極有可能致使504 Gateway Time-out如今的網站, 尤爲某些論壇有大量的回覆和不少內容的, 一個頁面甚至有幾百K默認的fastcgi進程響應的緩衝區是8K, 咱們能夠設置大點在nginx.conf裏, 加入:web
fastcgi_buffers 8 128k 這表示設置fastcgi緩衝區爲8×128k,固然若是您在進行某一項即時的操做, 可能須要nginx的超時參數調大點, 例如設置成60秒: send_timeout 60; 只是調整了上面這兩個參數, 結果可能就是沒有再顯示那個超時! 解決辦法:調整nginx.conf的相關設置: fastcgi_connect_timeout 600; fastcgi_send_timeout 600; fastcgi_read_timeout 600; fastcgi_buffer_size 256k; fastcgi_buffers 16 256k; fastcgi_busy_buffers_size 512k; fastcgi_temp_file_write_size 512k;
2)502 錯誤
502主要針對B 、C階段。產生502的時候,對應的error_log中的內容會有好幾種:數據庫
access_logvim
[16/May/2016:16:39:49 +0800] 10.4.31.56 201605161639490100040310562612 2612221463387989972 10.6.19.81 127.0.0.1:88 "GET /articles/?source_type=0 HTTP/1.1" 503 **.***.com **.**.**.4, **.**.**.160 0.000 0.000 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36" "uuid=\x22w:546d345b86ca443eb44bd9bb1120e821\x22; tt_webid=15660522398; lasttag=news_culture; sessionid=f172028cc8310ba7f503adb5957eb3ea; sid_tt=f172028cc8310ba7f503adb5957eb3ea; _ga=GA1.2.354066248.1463056713; _gat=1"
error_log後端
2016/05/16 16:39:49 [error] 90693#0: *944980723 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 10.6.19.80, server: **.***.com, request: "GET /articles/ HTTP/1.1", upstream: "http://127.0.0.1:8500/**/**/articles/", host: "**.***.com", referrer: "http://**.***.com/new_article/"
列一下常見的幾種502對應的 error_log:api
這些都表明,在nginx設置的超時時間內,上游uwsgi沒有給正確的響應(可是是有響應的,否則若是一直沒響應,就會變成504超時了),所以nginx這邊的狀態碼爲502。bash
如上,access_log中出現503,爲何?
這個是由於nginx upstream的容災機制。若是nginx有以下配置:
upstream app_backup { server 127.0.0.1:8500 max_fails=3 fail_timeout=5s; server 127.0.0.1:88 backup; }
proxy_next_upstream error http_502; proxy_connect_timeout 1s; proxy_send_timeout 6s; proxy_read_timeout 10s; proxy_set_header Host $host;
server { listen 88; access_log /var/log/nginx/failover.log; expires 1m; error_page 500 502 503 504 /500.html; location / { return 503; } location = /500.html { root /**/**/**/nginx/5xx/; } }
這個的意思就是,對於訪問88端口的請求,nginx會返回503狀態碼,同時返回/opt/tiger/ss_conf/nginx/5xx/這個路徑下的500.html文件。
所以,access_log中看到的是503。
Nginx 502 Bad Gateway的含義是請求的PHP-CGI已經執行,可是因爲某種緣由(通常是讀取資源的問題)沒有執行完畢而致使PHP-CGI進程終止。Nginx 502錯誤的緣由比較多,通常就是由於在代理模式下後端服務器出現問題引發的。這些錯誤通常都不是nginx自己的問題,必定要從後端找緣由!好比:php-cgi進程數不夠用、php執行時間長、或者是php-cgi進程死掉,都會出現502錯誤。502錯誤最一般的出現狀況就是後端主機宕機!!
通常來講Nginx 502 Bad Gateway和php-fpm.conf的設置有關,php-fpm.conf有兩個相當重要的參數,一個是"max_children",另外一個是"request_terminate_timeout" ,可是這個值不是通用的,而是須要本身計算的。
計算的方式以下:
1)request_terminate_timeout
若是服務器性能足夠好,且寬帶資源足夠充足,PHP腳本沒有系循環或BUG的話你能夠直接將"request_terminate_timeout"設置成0s。0s的含義是讓PHP-CGI一直執行下去而沒有時間限制。而若是你作不到這一點,也就是說你的PHP-CGI可能出現某個BUG,或者你的寬帶不夠充足或者其餘的緣由致使你的PHP-CGI可以假死那麼就建議你給"request_terminate_timeout"賦一個值,這個值能夠根據你服務器的性能進行設定。通常來講性能越好你能夠設置越高,20分鐘 -30分鐘均可以。因爲個人服務器PHP腳本須要長時間運行,有的可能會超過10分鐘所以我設置了900秒,這樣不會致使PHP-CGI死掉而出現502 Bad gateway這個錯誤。
2)max_children
max_children這個值又是怎麼計算出來的呢?這個值原則上是越大越好,php-cgi的進程多了就會處理的很快,排隊的請求就會不多。設置"max_children"也須要根據服務器的性能進行設定,通常來講一臺服務器正常狀況下每個php-cgi所耗費的內存在20M左右,所以個人"max_children"我設置成40個,20M*40=800M也就是說在峯值的時候全部PHP-CGI所耗內存在800M之內,低於個人有效內存1Gb。而若是個人"max_children"設置的較小,好比5-10個,那麼 php-cgi就會「很累",處理速度也很慢,等待的時間也較長。若是長時間沒有獲得處理的請求就會出現504 Gateway Time-out這個錯誤,而正在處理的很累的那幾個php-cgi若是遇到了問題就會出現502 Bad gateway這個錯誤。
=================502的解決辦法================
通常解決辦法
遇到502問題,能夠優先考慮按照如下兩個步驟去解決。 1)查看當前的PHP FastCGI進程數是否夠用:) netstat -anpo | grep "php-cgi" | wc -l 若是實際使用的「FastCGI進程數」接近預設的「FastCGI進程數」,那麼,說明「FastCGI進程數」不夠用,須要增大。 # ps aux | grep php-cgi |wc -l 130 # netstat -anpo | grep "php-cgi" | wc -l 450 # netstat -anpo | grep "php-cgi" |more tcp 0 0 192.168.12.201:52719 192.168.12.203:13002 ESTABLISHED 27687/php-cgi off (0.00/0/0) tcp 0 0 192.168.12.201:52713 192.168.12.203:13002 ESTABLISHED 27685/php-cgi off (0.00/0/0) tcp 0 0 192.168.12.201:52694 192.168.12.203:13002 ESTABLISHED 27682/php-cgi off (0.00/0/0) tcp 0 0 192.168.12.201:52688 192.168.12.203:13002 ESTABLISHED 27681/php-cgi off (0.00/0/0) tcp 0 0 192.168.12.201:52701 192.168.12.203:13002 ESTABLISHED 27683/php-cgi off (0.00/0/0) 重啓php服務後 # netstat -anpo | grep "php-cgi" | wc -l 46 2)部分PHP程序的執行時間超過了Nginx的等待時間,能夠適當增長nginx.conf配置文件中FastCGI的timeout時間,例如: ...... http { ...... fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; ...... } ...... php.ini中memory_limit設低了會出錯,修改了php.ini的memory_limit爲128M,重啓nginx,發現好了,原來是PHP的內存不足了。
臨時解決辦法
Nginx提示502和504錯誤的臨時解決辦法是:調整php-fpm.conf的相關設置: <value name=」max_children」>32</value> <value name=」request_terminate_timeout」>30s</value> fast-cgi的執行腳本時間
終級解決方案
以上解決方案只能臨時解決問題,而若是網站的訪問量確實很是很是大,而Nginx+FastCGI只能對處理瞬間或短期內的高併發有很好的效果, 因此目前惟一的終極解決方案是:定時平滑重啓php-cgi。 1)寫一個很是簡單的腳本: # vim /home/www/scripts/php-fpm.sh #!/bin/bash # This script run at */1 /usr/local/php/sbin/php-fpm reload 2)將腳本添加至計劃任務:) # crontab -e */1 * * * * /home/www/scripts/php-fpm.sh 爲了省事起見,也能夠不寫腳本,直接在crontab裏寫入php-fpm的平滑重啓命令。
Nginx 502錯誤狀況
1))網站的訪問量大,而php-cgi的進程數偏少。 針對這種狀況的502錯誤,只需增長php-cgi的進程數。具體就是修改/usr/local/php/etc/php-fpm.conf 文件,將其中的max_children值適當增長。 這個數據要依據你的VPS或獨立服務器的配置進行設置。通常一個php-cgi進程佔20M內存,你能夠本身計算下,適量增多。 /usr/local/php/sbin/php-fpm restart 而後重啓一下. 2))CPU佔用率、內存佔用率很是高,遭到CC攻擊. 解決方法請參考:Linux VPS簡單解決CC攻擊 3)CPU佔用率不高,內存溢出。 檢查一下網站程序有沒有問題?通常小偷站點經常會出現內存溢出。 檢查一下/var/log/目錄下的日誌,看看是否是有人爆破SSH和FTP端口? SSH、FTP遭到窮舉也會佔用大量內存。是的話改掉SSH端口和FTP端口便可。
3)499錯誤
client發送請求後,若是在規定的時間內(假設超時時間爲500ms)沒有拿到nginx給的響應,則認爲此次請求超時,會主動結束,這個時候nginx的access_log就會打印499狀態碼。
A+B+C+D > 500ms
其實這個時候,server端有可能還在處理請求,只不過client斷掉了鏈接,所以處理結果也沒法返回給客戶端。
499若是比較多的話,可能會引發服務雪崩。
好比說,client一直在發起請求,客戶端由於某些緣由處理慢了,沒有在規定時間內返回數據,client認爲請求失敗,中斷此次請求,而後再從新發起請求。這樣不斷的重複,服務端的請求愈來愈多,機器負載變大,請求處理愈來愈慢,沒有辦法響應任何請求
官網總結nginx返回499的狀況,是因爲:
client has closed connection #客戶端主動關閉了鏈接。
client has closed connection #客戶端主動關閉了鏈接。
client has closed connection #客戶端主動關閉了鏈接。
解決的話,能夠添加
proxy_ignore_client_abort on;
還有一種緣由,確實是客戶端關閉了鏈接,或者鏈接超時。主要是由於PHP進程數太少,或php進程佔用,資源不能很快釋放,請求堆積。這種狀況要解決的話,須要在程序上作優化。
499報錯便是客戶端關閉鏈接,這個狀態碼並非http協議中定義的status code,而是nginx本身定義的一個狀態碼。因爲服務器處理請求較多,客戶端在有效時間內沒有獲得答覆,主動關閉了鏈接。有人說把時間設置長一些或者使用proxy_ignore_client_abort on(讓代理服務端不要主動關閉客戶端的鏈接)。可是這樣也有必定的風險,會拖垮服務器。發生這個錯誤,若是服務器CPU和內存不算過高,通常是數據庫和程序的問題,數據庫處理較慢或者程序線程較低。結合狀況調整,好比讀寫分離或者程序線程數調高。
4)500錯誤
服務器內部錯誤,也就是服務器遇到意外狀況,而沒法執行請求。發生錯誤,通常的幾種狀況:
分析錯誤的緣由
5)503錯誤
503是服務不可用的返回狀態。
因爲在nginx配置中,設置了limit_req的流量限制,致使許多請求返回503錯誤代碼,在限流的條件下,爲提升用戶體驗,但願返回正常Code 200,且返回操做頻繁的信息:
location /test { ... limit_req zone=zone_ip_rm burst=1 nodelay; error_page 503 =200 /dealwith_503?callback=$arg_callback; } location /dealwith_503{ set $ret_body '{"code": "V00006","msg": "操做太頻繁了,請坐下來喝杯茶。"}'; if ( $arg_callback != "" ) { return 200 'try{$arg_callback($ret_body)}catch(e){}'; } return 200 $ret_body; }
6)400錯誤:request header or cookie too large
解決辦法: 修改nginx.conf,添加下面內容(即增長緩衝區) [root@fvtlb01 ~]# vim /data/nginx/conf/nginx.conf ...... http { ...... client_header_buffer_size 8k; #默認是4k(能夠稍微改大,好比16K) large_client_header_buffers 4 8k; ...... }
=================nginx日誌"110: Connection timed out"報錯=================
訪問nginx頁面,出現5xx報錯。查看nginx日誌,發現以下報錯信息: upstream timed out (110: Connection timed out) while reading response header from upstream 解決辦法:修改fastcgi_read_timeout的時間值,默認是60s,好比能夠改爲600s或3000s
................................................Nginx Code Status...............................
200:服務器成功返回網頁 403:服務器拒絕請求。 404:請求的網頁不存在 499:客戶端主動斷開了鏈接。 500:服務器遇到錯誤,沒法完成請求。 502:服務器做爲網關或代理,從上游服務器收到無效響應。 503 - 服務不可用 504:服務器做爲網關或代理,可是沒有及時從上游服務器收到請求。 這些狀態碼被分爲五大類: 100-199 用於指定客戶端應相應的某些動做。 200-299 用於表示請求成功。 300-399 用於已經移動的文件而且常被包含在定位頭信息中指定新的地址信息。 400-499 用於指出客戶端的錯誤。 (本身電腦這邊的問題) 本身電腦這邊的問題) 500-599 用於支持服務器錯誤。 (對方的問題) 對方的問題) --------------------------------------------------------------------------------------------- 200 (成功) 服務器已成功處理了請求。 一般,這表示服務器提供了請求的網頁。 201 (已建立) 請求成功而且服務器建立了新的資源。 202 (已接受) 服務器已接受請求,但還沒有處理。 203 (非受權信息) 服務器已成功處理了請求,但返回的信息可能來自另外一來源。 204 (無內容) 服務器成功處理了請求,但沒有返回任何內容。 205 (重置內容) 服務器成功處理了請求,但沒有返回任何內容。 206 (部份內容) 服務器成功處理了部分 GET 請求。 --------------------------------------------------------------------------------------------- 300 (多種選擇) 針對請求,服務器可執行多種操做。 服務器可根據請求者 (user agent) 選擇一項操做,或提供操做列表供請求者選擇。 301 (永久移動) 請求的網頁已永久移動到新位置。 服務器返回此響應(對 GET 或 HEAD 請求的響應)時,會自動將請求者轉到新位置。 302 (臨時移動) 服務器目前從不一樣位置的網頁響應請求,但請求者應繼續使用原有位置來進行之後的請求。 303 (查看其餘位置) 請求者應當對不一樣的位置使用單獨的 GET 請求來檢索響應時,服務器返回此代碼。 304 (未修改) 自從上次請求後,請求的網頁未修改過。 服務器返回此響應時,不會返回網頁內容。 305 (使用代理) 請求者只能使用代理訪問請求的網頁。 若是服務器返回此響應,還表示請求者應使用代理。 307 (臨時重定向) 服務器目前從不一樣位置的網頁響應請求,但請求者應繼續使用原有位置來進行之後的請求。 --------------------------------------------------------------------------------------------- 400 (錯誤請求) 服務器不理解請求的語法。 401 (未受權) 請求要求身份驗證。 對於須要登陸的網頁,服務器可能返回此響應。 403 (禁止) 服務器拒絕請求。 404 (未找到) 服務器找不到請求的網頁。 405 (方法禁用) 禁用請求中指定的方法。 406 (不接受) 沒法使用請求的內容特性響應請求的網頁。 407 (須要代理受權) 此狀態代碼與 401(未受權)相似,但指定請求者應當受權使用代理。 408 (請求超時) 服務器等候請求時發生超時。 409 (衝突) 服務器在完成請求時發生衝突。 服務器必須在響應中包含有關衝突的信息。 410 (已刪除) 若是請求的資源已永久刪除,服務器就會返回此響應。 411 (須要有效長度) 服務器不接受不含有效內容長度標頭字段的請求。 412 (未知足前提條件) 服務器未知足請求者在請求中設置的其中一個前提條件。 413 (請求實體過大) 服務器沒法處理請求,由於請求實體過大,超出服務器的處理能力。 414 (請求的 URI 過長) 請求的 URI(一般爲網址)過長,服務器沒法處理。 415 (不支持的媒體類型) 請求的格式不受請求頁面的支持。 416 (請求範圍不符合要求) 若是頁面沒法提供請求的範圍,則服務器會返回此狀態代碼。 417 (未知足指望值) 服務器未知足"指望"請求標頭字段的要求。 --------------------------------------------------------------------------------------------- 500 (服務器內部錯誤) 服務器遇到錯誤,沒法完成請求。 501 (還沒有實施) 服務器不具有完成請求的功能。 例如,服務器沒法識別請求方法時可能會返回此代碼。 502 (錯誤網關) 服務器做爲網關或代理,從上游服務器收到無效響應。 503 (服務不可用) 服務器目前沒法使用(因爲超載或停機維護)。 一般,這只是暫時狀態。 504 (網關超時) 服務器做爲網關或代理,可是沒有及時從上游服務器收到請求。 505 (HTTP 版本不受支持) 服務器不支持請求中所用的 HTTP 協議版本。
proxy_intercept_errors
當上遊服務器響應頭回來後,能夠根據響應狀態碼的值進行攔截錯誤處理,與error_page 指令相互結合。用在訪問上游服務器出現錯誤的狀況下。
以下的一個配置實例:
[root@dev ~]# cat ssl-zp.wangshibo.conf upstream mianshi1 { server 192.168.1.33:8080 max_fails=3 fail_timeout=10s; #server 192.168.1.32:8080 max_fails=3 fail_timeout=10s; } server { listen 443; server_name zp.wangshibo.com; ssl on; ### SSL log files ### access_log logs/zrx_access.log; error_log logs/zrx_error.log; ### SSL cert files ### ssl_certificate ssl/wangshibo.cer; ssl_certificate_key ssl/wangshibo.key; ssl_session_timeout 5m; error_page 404 301 https://zp.wangshibo.com/zrx-web/; location /zrx-web/ { proxy_pass http://mianshi1; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # proxy_set_header X-Forwarded-Proto https; #proxy_set_header X-Forwarded-Proto https; proxy_redirect off; proxy_intercept_errors on; } }