nginx+uwsgi搭建web服務的性能調優和問題處理

將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

  

2016-08-10更新:

運行時可能產生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;
        }

 

2016-08-29更新:

偶爾仍是會出現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

 

2016-12-05更新:

最近app搞活動訪問量增長很多,又開始出現502 error了,增長了uwsgi的線程數threads = 20,消滅了其中一部分,但仍是有不少訪問頻繁的服務會出現了502,開始從nginx配置查找緣由。

發現長鏈接竟然是打開的!若是你的服務器上請求量很大,那你最好仍是關閉這個參數吧,這樣很危險的。

如今的服務器CPU很強,因此不用考慮頻繁的tcp鏈接對cpu形成的壓力,故建議關閉你的長鏈接吧。

keepalive_timeout  0;

 

2017-3-21更新:

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爲新聞推薦接口單獨起了一個端口,這樣至少在掛了的時候不會影響到其餘接口正常使用,估計最終解決方案仍是要增長均衡負載。

相關文章
相關標籤/搜索