博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
nginx被动检测
阅读量:4210 次
发布时间:2019-05-26

本文共 5827 字,大约阅读时间需要 19 分钟。

     随着应用越来越多,tomcat容器也越来越重,随之而来的是tomcat宕机越来越频繁。最终选择jar包部署测试反向代理的效果。虽然jar包部署之后项目肯定会稳定很多。但是nginx宕机检测还是要做的。在本地调试发现并没有出现什么问题。就将nginx部署到了灰度环境。在项目跑起来之后我们直接关闭了其中一个项目。按照nginx反向代理的被动检测机制应该还是可以返回正常的数据。但是我们发现灰度的nginx宕机检测花费了21秒。这个时间有点太大了,用户估计要爆炸。想了好多也没找到问题。下面记录一下自己的狗血经历。

怎么发现21秒的问题?

在我两台服务停掉一台之后,再去访问项目页面。发现项目太慢,但是通过几次刷新就可以迅速快起来。但是过一段时间项目的又开始缓慢了,而且具有规律性。很快我就知道问题应该是fail_timeout的问题。

upstream kmdiscussj {    server kk.kkk.kk.165:8091 weight=1 max_fails=2 fail_timeout=30s;    server jj.jjj.jj.166:8091 weight=1 max_fails=2 fail_timeout=30s;}location ^~ /discuss/ {    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_pass http://kmdiscussj/discuss/;}

我将fial_timeout改成了4,然后max_fails改成了1。然后写了一个简单的python脚本每隔一秒请求一次接口,然后打印请求时间。试图确定真实的宕机检测时间。

import requestsimport timeheaders = {    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 '                  '(KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36','ignore-identity':'true'}def spiderForKm(url):    while 1:        start=time.time()        html=requests.get(url, headers=headers).content        end=time.time()        print(end-start)        time.sleep(1)        def main():    spiderForKm("https://kkkk.kkkk.com/discuss/mytest/v1/get")    if __name__ == "__main__":    main()

但是这21秒到底去哪里了。按照weight=1 max_fails=2 fail_timeout=30s的官方解释和python控制台的打印结果也没问题。为啥需要那么长时间?是nginx版本不对还是项目的问题还是网络问题?这让人很难,所以咋都得测试一遍。

当时用的nginx版本是1.12,有同事说是不是版本的问题。其实我感觉不太可能,但活马当死马医吧。就更新到了1.18版本。反正是灰度环境还没上线。但是通过测试还是发现神奇的21秒并没有消失。所以只能继续向后边排查。如果不是版本问题那是不是网络问题?但是如果是网络问题那21秒之后为啥又很快,难道是初次连接的时候会不识别?我觉得有必要看一下日志。找了半天发现日志的时间怎么都是一样的,zzz。这是什么鬼。想了好久,突然灵机一动这是不是响应时间?最后查了相关资料发现nginx默认认知是没有响应时间的,于是我们又开始配置日志了。

log_format main '$remote_addr - $remote_user [$time_local] "$request" '                '$status $body_bytes_sent "$http_referer" '                '"$http_user_agent" "$http_x_forwarded_for" '                '"$request_time"';

注意这个log_format要配置在http中。日志打印要配置到server中

access_log  logs/host.access.log  main;#其中的main是日志的定义。和上边的保持一致。

配置好日志之后,开启我们的python脚本,然后去看nginx的请求日志。发现响应时间确实是21秒。。。

想想看这21秒肯定是包括宕机检测的时间加正常请求的时间。所以宕机检测的时间至少也有20秒。如果要甩锅给运维的话时机还不成熟,可能还会被反杀。算了还是再定位一下吧。既然在灰度环境是21秒,那么我本地是多少秒。为了方便期间,我本地创建了两个测试项目其中就只有一个方法。然后在本地部署了nginx,然后代理到不同的端口,然后故意关闭一个服务。发现2秒就可以检测到。但为什么会灰度环境需要那么久?不应该是服务器性能更好吗?难道是灰度的应用服务太大,宕机检测需要的时间更长???我觉得这不可能吧,于是我将其中一个包放到灰度环境上。然后测试,发现还是花费了21秒时间,这就奇怪了。同样的项目,我本地2秒,线上21秒?而且所有的配置都一样,唯一的不同就是线上的nginx代理的应用比较多,大概有20个,每个部署2台,总计也超过20了,其中还有websocket。所以我怀疑是项目太多导致的。为此把nginx上的其他代理全部取消了。然后再看python控制台打印的结果。发现居然还是21秒。。。。。我奔溃了。

我都已经准备好说服领导接受这个现实,因为宕机的概率已经降低很多了,而且宕机检测虽然慢一点,但是项目接口还是会正常运行的。我们只需要将fail_timeout设置的大一点,这样就可以避免过多的超时检测。这样用户请求被转发到宕机的机器的可能性就会降低很多,当然我还在怀疑是不是网络的问题。我记得有个read_timeout和send_timeout。但是我本地都没配置这个,2秒就可以检测成功。为啥线上需要那么久?显然应该也不是这两个参数的问题。

但是怀着学习的心态还是仔细学习了这个参数的意义

proxy_send_timeout=60s;表示请求发送给上游服务的超时时间,默认为60秒

proxy_read_timeout=60s;表示nginx从上游服务读取返回的超时时间,也就是上游服务处理请求时间加网络通信时间的最大时间。默认为60秒 

无意中发现了nginx中的proxy_connect_timeout的配置。

proxy_connect_timeout表示nginx与上游服务的连接超时时间。默认为60秒。想想看如果没有连接上是不是会在60秒的时间范围内进行尝试,然后等待。问题是不是在这里?我马上将这个配置添加到nginx的location中,并将值设置为4,然后观察python控制台

   proxy_connect_timeout 4s;     proxy_send_timeout 4s;     proxy_read_timeout 4s;

整个人都愉快了好多。想着能不能再降低一下,我将上边的配置中4全部设置成了1,控制台的时间也变成了1点多,但是访问页面的时候发现接口开始没有响应了。一直没有返回值。然后也没开始报告说让查看nginx日志。怀疑是send_timeout和read_timeout太小导致的死循环。所有我将    proxy_send_timeout 和 proxy_read_timeout 都设置为8,问题解决。但是想着 proxy_connect_timeout 1s; 有点太短,所以还是将其设置为2并重启reload了nginx的配置。果然即便宕机了,nginx的最大延迟时间也就2秒。总体上还是可以接受的。

问题解决完毕之后,感觉整个人都轻松了好多。

在此记录了一下其他的问题。

1.具有websocket的项目,由于项目websocket可以采用http1.1来维持单机的唯一链路,但是接口可能会被路由到不同的机器,从而导致websocket不能及时将消息广播到用户。使用ip_hash也不能解决问题。最好的方法是将websocket和接口分离。或者如果分离不开的话就需要对接mq的广播机制了。

2.如果采用threadlocal缓存前端某个标志,可能需要采用ip_hash,否则会被路由到不同机器,然后导致业务出现错误 。

在此贴一下nginx的配置

events {    worker_connections  1024;}http {    include       mime.types;    default_type  application/octet-stream;    client_max_body_size 500M;    keepalive_timeout  65;      log_format main '$remote_addr - $remote_user [$time_local] "$request" '                  '$status $body_bytes_sent "$http_referer" '                  '"$http_user_agent" "$http_x_forwarded_for" '                  '"$request_time"';      map $http_upgrade $connection_upgrade {           default upgrade;           '' close;       }     upstream kmdiscussj {       server kk.kkk.kk.165:8091 weight=1 max_fails=2 fail_timeout=30s;        server jj.jjj.jj.166:8091 weight=1 max_fails=2 fail_timeout=30s;    }    upstream kmsocket{        ip_hash;        server kk.kkk.kk.165:8091;        server jj.jjj.jj.166:8091;        keepalive 1000;    }    server {        listen       80;        server_name xxx.xx.com;        access_log  logs/host.access.log  main;        location ^~ /socket.io/ {            proxy_connect_timeout 4s;             proxy_send_timeout 12s;             proxy_http_version 1.1;             proxy_redirect off;            proxy_set_header Host $host;             proxy_set_header X-Real-IP $remote_addr;             proxy_read_timeout 3600s;             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;             proxy_set_header Upgrade $http_upgrade;            proxy_set_header Connection "upgrade";            proxy_set_header Connection $connection_upgrade;            proxy_pass http://kmsocket/socket.io/;        }          location ^~ /discuss/ {            proxy_connect_timeout 2s;             proxy_send_timeout 8s;             proxy_read_timeout 8s;             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_pass http://kmdiscussj/discuss/;        }        error_page   500 502 503 504  /50x.html;        location = /50x.html {            root   html;        }    }}

其他:

windows环境的关闭nginx,taskkill /im nginx.exe /f

转载地址:http://vqkmi.baihongyu.com/

你可能感兴趣的文章
剑指offer——从前序遍历和中序遍历重建二叉树
查看>>
剑指offer——求二叉树的深度
查看>>
剑指offer——二叉树的镜像
查看>>
剑指offer——翻转链表
查看>>
使用sort对map的val值进行排序
查看>>
小记DB2远程连接不上解决
查看>>
[转]DB2监控sql
查看>>
Websphere was生成javacore
查看>>
WebSphere增加80端口
查看>>
DB2快速创建测试库
查看>>
利用db2look查看ddl
查看>>
rm -f 血的教训
查看>>
[转]java对HashMap深度解析
查看>>
[转]LinkedHashMap特性 按插入和访问顺序排序
查看>>
Hessian4.0.7反序列化BigDecimal类型Bug
查看>>
[转]Spring AOP 配置
查看>>
HashMap无序与LinkedHashMap有序
查看>>
Spring异步任务@asynch
查看>>
Curl实现web serivce调试调用
查看>>
Tomcat NioEndPoint初探
查看>>