将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为新闻推荐接口单独起了一个端口,这样至少在挂了的时候不会影响到其余接口正常使用,估计最终解决方案仍是要增长均衡负载。