首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >nginx被动检测

nginx被动检测

作者头像
写一点笔记
发布2020-08-25 14:31:18
5510
发布2020-08-25 14:31:18
举报

随着应用越来越多,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 requests
import time

headers = {
    '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
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员备忘录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档