出现问题的原因是请求压力大,服务器listen后不能及时接受socket,新来的connection就建立不起来,而这背后可能是由于部分api处理慢,影响了整体组件的可用性,也可能是程序的并发性不高。
可以从三个方面来优化:
修改配置参数来优化性能
(1)修改系统配置参数:
vi /etc/sysctl.conf
在文件末尾添加:
net.core.somaxconn = 65535 #服务端所能接受处理数据的连接上限,此时TCP三次握手已完成,该数值不能超过65536
net.ipv4.tcp_max_syn_backlog = 8192 #服务端能容纳半连接的上限,此时服务端处于TCP三次握手中的SYN_REVD状态
net.core.netdev_max_backlog = 65535 # 网卡设备将请求放入队列的长度,数据包的接收速度大于内核tcp处理速度时,会进入该队列
然后执行以下命令重新load参数,会立即生效,之后重启机器也会生效
sysctl -p
(2)修改nginx 的配置参数
worker_processes 2; #设置为cpu的个数
events {
worker_connections 65535; # 最大连接数,这个值依赖系统的配置
}
(3)修改uwsgi.ini的配置参数
增加uwsgi listen 队列长度和工作进程的数量,在uwsgi的配置文件中添加以下配置:
listen = 1024
processes = 8
采用UNIX Domain Socket 来替代网络Socket
首先介绍一下UNIX Domain Socket 和 网络Socket的联系与区别:
联系:都是进程间通信的机制
区别:
(1)UNIX Domain Socket只能用于同一台机器上不同进程之间的通信,而网络Socket还可以用于不同机器上进程之间的通信;
(2)通过UNIX Domain Socket进行进程间通信时,不需要经过网络协议栈、不需要数据的打包和拆包、计算校验和、维护序列号和应答等,只是将应用层数据从一个进程拷贝到另一个进程;通过UNIX Domain Socket通信在同一台机器上传输速度是网络Socket的两倍;
(3)UNIX Domain Socket是可靠的,消息不会丢失、不会乱序,而使用UDP的网络Socket通信是不可靠的;
(4)网络socket地址是IP地址加端口号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用创建,如果调用bind()时该文件已存在,则bind()错误返回。
那么我们应该如何修改我们的配置参数呢?
(1)修改uwsgi.ini的配置参数
增加uwsgi listen 队列长度和工作进程的数量,在uwsgi的配置文件中添加以下配置:
socket = /tmp/uwsgi.sock # 变为UNIX Domain Socket 而127.0.0.1:5000 为网络Socket
(2)修改nginx 的server中的配置参数
uwsgi_pass unix:///tmp/uwsgi.sock; #之前是127.0.0.1:5000
增加机器 利用nginx的负载均衡
修改nginx的配置参数:
在http{}中添加以下内容
upstream backend {
server 192.168.102.133:8077 ; #换成自己的生产机器Socket,与nginx配置在同一台机器的server可写UNIX Domain Socket
server 192.168.102.134:8077 ;
server 192.168.102.135:8077;
#ip_hash; 如果有session一致性问题
}
在server{}中添加以下内容:
location / {
include uwsgi_params;
uwsgi_pass backend;
proxy_redirect off;
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-Host $server_name;
}
最后别忘记重新启动nginx。
网友评论