將nginx +uwsgi+flask架構來搭建web服務。可是發現一個問題,若是http請求達到必定量後,nginx直接返回502。python
大概知道問題應該在nginx和uwsgi上,限制了併發的處理數。nginx
查了nginx uwsgi官方的資料。原來調優有好幾個參數,而且系統自己也須要作一些調優web
1.首先先看一下nginx.conf裏影響處理的配置。json
user nginx; worker_processes xx; #能夠設置成cpu個數,體驗較佳的性能 error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; worker_rlimit_nofile 65535; # 最大打開文件數,這個值須要<= worker_connections events { worker_connections 65535; # 最大鏈接數,這個值依賴系統的配置。 }
2.看一下系統的配置sysctl.confflask
net.core.somaxconn = 2048 #定義了系統中每個端口最大的監聽隊列的長度,這是個全局的參數。默認是128.優化能夠根據系統配置作優化
3.uwsgi 的配置優化/etc/uwsgi.d/admin.ini後端
workers = 24 # 併發處理進程數 listen = 65535 # 併發的socket 鏈接數。默認爲100。優化須要根據系統配置
在作優化以前,發現併發數過不了100.緣由就是這裏,uwsgi 的socket 默認連接爲100.api
作完調優,在此壓測了一下性能,併發爲10000時:bash
ab -r -n 100000 -c 10000 -H "User-Agent: python-keystoneclient" -H "Accept: application/json" -H "X-Auth-Token: 65e194" http://keystonehost:35357/v2.0/
壓測報告:服務器
Server Software: nginx/1.8.1 Server Hostname: keystonehost Server Port: 35357 Document Path: /v2/ Document Length: 450 bytes Concurrency Level: 15000 Time taken for tests: 30.136 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Total transferred: 72900000 bytes HTML transferred: 45000000 bytes Time per request: 4520.417 [ms] (mean) Transfer rate: 2362.33 [Kbytes/sec] received
運行時可能產生504 Gateway Time out這樣的錯誤,究其緣由是由於相關參數設置的不當。網絡
nginx和uwsgi整合時有三個參數能夠用於設置超時時間,在nginx配置文件http->server->location中設置。
proxy_connect_timeout:默認60秒,與uwsgi-server鏈接的超時時間,該值不能超過75秒.若在超時時間內未能成功鏈接則斷開鏈接嘗試。
proxy_read_timeout:默認60秒,nginx等待uwsgi進程發送響應數據的超時時間。如有須要長時間運行才能產生輸出結果的uwsgi進程則需將此參數調高。若在錯誤日誌文件中看到 upstream timed out需將此參數調高。若超過超時時間還未收到響應則nginx關閉鏈接。
proxy_send_timeout:默認60秒,nginx向uwsgi進程發送請求的超時時間。超時時間由兩次寫操做的時間間隔算,而非整個請求。若超過超時時間仍沒寫入動做則nginx關閉鏈接。
出現504錯誤的接口主要是讀取新聞內容進行解析,多是正文過長致使讀取數據超時,所以將proxy_read_timeout設爲150,問題解決。
location /news/quality { proxy_pass http://web1; 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_ignore_client_abort on; proxy_read_timeout 150; access_log /var/log/nginx/access.log main; }
偶爾仍是會出現502的error,查看了nginx的錯誤日誌發現:
2016/08/29 01:00:51 [error] 9195#9195: *432169941 upstream prematurely closed connection while reading response header from upstream
查了資料後發現應該是socket 超時時間設置太短,默認是4s,uwsgi配置修改爲10s後到目前爲止正常。
http = 0.0.0.0:10053
socket-timeout=10
最近app搞活動訪問量增長很多,又開始出現502 error了,增長了uwsgi的線程數threads = 20,消滅了其中一部分,但仍是有不少訪問頻繁的服務會出現了502,開始從nginx配置查找緣由。
發現長鏈接竟然是打開的!若是你的服務器上請求量很大,那你最好仍是關閉這個參數吧,這樣很危險的。
如今的服務器CPU很強,因此不用考慮頻繁的tcp鏈接對cpu形成的壓力,故建議關閉你的長鏈接吧。
keepalive_timeout 0;
app投票活動致使訪問量再次激增,app後端的限制作的薄弱,致使流量攻擊的狀況持續發生。咱們數據部這邊的日接口調用量已經超過了100w+,今天有幾個接口頻繁報錯502和504. 根據前面幾回的排查來看nginx和uwsgi的線程數應該是足夠的,在uwsgi日誌定位到錯誤log:
應該是listen 隊列滿的緣由,主要緣由是因爲部分api (新聞推薦接口)處理慢,影響了內部雲平臺其餘api的可用性。在併發較高的狀況下就會出現該問題;直接後果就是其餘api不能正常提供服務;
處理方法有如下3種:
(1)增長uwsgi listen 隊列長度 :經過參數 --listen 1024 來提升監聽長度;
(2)使用UNIX Domain Socket 來替代網絡Socket ,它不須要通過網絡協議棧,不須要打包拆包等操做,它只是將應用程序數據從一個進程cp到另外一個進程,這正好適合nginx 和 uwsgi 在同一臺機器的狀況;經過 --socket /tmp/uwsgi.sock 來使用 Domain Socket;
(3)增長負載均衡,把壓力均分到其餘機器上;
第二種方法測試沒法啓用,第三種方法機器暫不夠用,只能經過增長uwsgi listen 隊列長度,添加--listen 2048依然不夠,最後調整到10w,發現過一會仍是會被阻塞。增長隊列長度別忘了先修改系統參數,方法以下:
修改系統參數 這裏直接修改配置文件了,重啓後仍然有效。 修改/etc/sysctl.conf文件,添加或者修改這幾個參數值 #對於一個常常處理新鏈接的高負載 web服務環境來講,默認的 128 過小了 net.core.somaxconn = 262144 #表示SYN隊列的長度,默認爲1024,加大隊列長度爲8192,能夠容納更多等待鏈接的網絡鏈接數 net.ipv4.tcp_max_syn_backlog = 8192 #網卡設備將請求放入隊列的長度 net.core.netdev_max_backlog = 65536 修改完成以後要記得 sysctl -p 從新加載參數
臨時解決方案最終是在nginx爲新聞推薦接口單獨起了一個端口,這樣至少在掛了的時候不會影響到其餘接口正常使用,估計最終解決方案仍是要增長均衡負載。