压测引发的 nginx报错 502 no live upstreams while connecting to upstream解决

对系统的某个接口进行极限压测,随着并发量上升,nginx开始出现502 no live upstreams while connecting to upstream的报错,维持最大并发量一段时间,发现调用接口一直返回502,即nginx已经发现不了存活的后端了。mysql

经过跟踪端口,发现nginx 跟后端建立了大量的链接。这很明显是没有使用http1.1长链接致使的。所以在upstream中添加keepalive配置。nginx

upstream yyy.xxx.web{
    server 36.10.xx.107:9001;
    server 36.10.xx.108:9001;

    keepalive 256;
}
server {
    ···
    location /zzz/ {
        proxy_pass http://yyy.xxx.web;
        ···   
    }
}

根据官方文档的说明:该参数开启与上游服务器之间的链接池,其数值为每一个nginx worker能够保持的最大链接数,默认不设置,即nginx做为客户端时keepalive未生效。web

默认状况下 Nginx 访问后端都是用的短链接(HTTP1.0),一个请求来了,Nginx 新开一个端口和后端创建链接,请求结束链接回收。若是配置了http 1.1长链接,那么Nginx会以长链接保持后端的链接,若是并发请求超过了 keepalive 指定的最大链接数,Nginx 会启动新的链接来转发请求,新链接在请求完毕后关闭,并且新创建的链接是长链接。redis

上图是nginx upstream keepalive长链接的实现原理。sql

首先每一个进程须要一个connection pool,里面都是长链接,多进程之间是不须要共享这个链接池的。 一旦与后端服务器创建链接,则在当前请求链接结束以后不会当即关闭链接,而是把用完的链接保存在一个keepalive connection pool里面,之后每次须要创建向后链接的时候,只须要从这个链接池里面找,若是找到合适的链接的话,就能够直接来用这个链接,不须要从新建立socket或者发起connect()。这样既省下创建链接时在握手的时间消耗,又能够避免TCP链接的slow start。若是在keepalive链接池找不到合适的链接,那就按照原来的步骤从新创建链接。 我没有看过nginx在链接池中查找可用链接的代码,可是我本身写过redis,mysqldb的链接池代码,逻辑应该都是同样的。谁用谁pop,用完了再push进去,这样时间才O(1)。 后端

须要注意的是:我在个人nginx1.12.0版本中新增该配置以后,再次压测,502问题依然存在,升级到1.16.0版本以后,502问题解决。缘由是nginx1.12.0版本不支持长链接配置。服务器

另外,若是nginx所在服务器和创建链接后端服务所在服务器不在同一网段时(即两台机器之间存在防火墙),还须要注意防火墙对长链接的影响。并发

 

 

参考:http://xiaorui.cc/2016/06/26/%E8%AE%B0%E4%B8%80%E6%AC%A1%E5%8E%8B%E6%B5%8B%E5%BC%95%E8%B5%B7%E7%9A%84nginx%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%80%A7%E8%83%BD%E8%B0%83%E4%BC%98/socket

相关文章
相关标签/搜索