从一起丢包故障来谈谈 nginx 中的 tcp keep-alive

栏目: 服务器 · Nginx · 发布时间: 5年前

内容简介:基本架构如图所示,客户端发起 http 请求给 nginx,nginx 转发请求给网关,网关再转发请求到后端微服务。故障现象是,每隔十几分钟或者几个小时不等,客户端就会得到一个或者连续多个请求超时错误。查看 nginx 日志,对应请求返回 499;查看网关日志,没有收到对应的请求。

一、故障

从一起丢包故障来谈谈 nginx 中的 tcp keep-alive

基本架构如图所示,客户端发起 http 请求给 nginx,nginx 转发请求给网关,网关再转发请求到后端微服务。

故障现象是,每隔十几分钟或者几个小时不等,客户端就会得到一个或者连续多个请求超时错误。查看 nginx 日志,对应请求返回 499;查看网关日志,没有收到对应的请求。

从日志分析,问题应该处在 nginx 或者 spring-cloud-gateway 上。

nginx 版本:1.14.2,spring-cloud 版本:Greenwich.RC2。

nginx 主要配置如下:

[root@wh-hlwzxtest1 conf]# cat nginx.conf

worker_processes  8;

events {
    use epoll;
    worker_connections  10240;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile       on;
    tcp_nopush     on;
    tcp_nodelay    on;

    keepalive_timeout  65;
    #gzip  on;

    upstream dbg2 {
        server 10.201.0.27:8888;
        keepalive 100;
    }

   server {
        listen       80;
        server_name  localhost;

        charset utf-8;

        location /dbg2/ {
            proxy_pass         http://dbg2/;
            proxy_http_version  1.1;
            proxy_set_header    Connection "";
         }
    }
}

为了提高性能,nginx 发送给网关的请求为 http 1.1,可以复用 tcp 连接。

二、排查

1、查看 tcp 连接

[root@10.197.0.38 logs]# ss -n | grep 10.201.0.27:8888
tcp    ESTAB      0      0      10.197.0.38:36674              10.201.0.27:8888
tcp    ESTAB      0      0      10.197.0.38:40106              10.201.0.27:8888

[root@10.201.0.27 opt]# ss -n | grep 10.197.0.38
tcp    ESTAB      0      0        ::ffff:10.201.0.27:8888                 ::ffff:10.197.0.38:40106
tcp    ESTAB      0      0        ::ffff:10.201.0.27:8888                 ::ffff:10.197.0.38:39266

可以看到 nginx 和网关之间建立的 socket 连接为 (10.201.0.27:8888,10.197.0.38:40106),另外的 2 条记录就很可疑了。猜测原因是:一端异常关闭了 tcp 连接却没有通知对端,或者通知了对端但对端没有收到。

2、抓包分析

先看下 nginx 的抓包数据:

从一起丢包故障来谈谈 nginx 中的 tcp keep-alive

序号 8403:转发 http 请求给网关;

序号 8404:在 RTT 时间内没有收到 ack 包,重发报文;

序号 8505:RTT 约等于 0.2s,tcp 重传;

序号 8506:0.4s 没收到 ack 包,tcp 重传;

序号 8507:0.8s 没收到 ack 包,tcp 重传;

序号 8509:1.6s 没收到 ack 包,tcp 重传;

...

序号8439:28.1s(128RTT)没收到 ack 包,tcp 重传。

序号 8408:请求设置了超时时间为 3s,因此发送 FIN 包。

再看下网关的抓包数据:

从一起丢包故障来谈谈 nginx 中的 tcp keep-alive

序号 1372:17:24:31 收到了 nginx 发过来的 ack 确认包,对应 nginx 抓包图中的序号 1348(nginx 那台服务器时间快了差不多 1 分 30 秒);

序号 4221:2 小时后,发送 tcp keep-alive 心跳报文,(从 nginx 抓包图中也可以看出这 2 小时之内该 tcp 连接空闲);

序号 4253:75s 后再次发送 tcp keep-alive 心跳;

序号 4275:75s 后再次发送心跳;

连续 9 次;

序号 4489:发送 RST 包,通过对端重置连接。

2 小时,75s, 9 次,系统默认设置。

[root@eureka2 opt]# cat /proc/sys/net/ipv4/tcp_keepalive_time
7200
[root@eureka2 opt]# cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75
[root@eureka2 opt]# cat /proc/sys/net/ipv4/tcp_keepalive_probes
9

具体这几个参数的作用,参考文章: 为什么基于TCP的应用需要心跳包

3、分析

通过以上抓包分析,基本确认了问题出在 nginx 上。19:25 时,网关发送 tcp keep-alive 心跳包给 nginx 那台服务器,此时那台服务器上保留着该 tcp 连接,却没有回应;22:20 时,nginx 发送 http 请求给网关,而网关已经关闭该 tcp 连接,因此没有应答。

三、解决

1、proxy_send_timeout

nginx 中与 upstream 相关的超时配置主要有如下参数,参考: Nginx的超时timeout配置详解

proxy_read_timeout:nginx 接收 upstream server 数据超时, 默认 60s, 如果连续的 60s 内没有收到 1 个字节, 连接关闭;
proxy_send_timeout:nginx 发送数据至 upstream server 超时, 默认 60s, 如果连续的 60s 内没有发送 1 个字节, 连接关闭。

这几个参数,都是针对 http 协议层面的。比如 proxy_send_timeout = 60s,并不是指如果 60s 没有发送 http 请求,就关闭连接;而是指发送 http 请求后,在两次 write 操作期间,如果超过 60s,就关闭连接。所以这几个参数,显然不是我们需要的。

2、upstream 模块的 keepalive_timeout 参数

查看官网文档, Module ngx_http_upstream_module

Syntax:    keepalive_timeout timeout;
Default:    
keepalive_timeout 60s;
Context:    upstream
This directive appeared in version 1.15.3.

Sets a timeout during which an idle keepalive connection to an upstream server will stay open.

设置 tcp 连接空闲时间超过 60s 后关闭,这正是我们需要的。

为了使用该参数,升级 nginx 版本到 1.15.8,配置文件如下:

http {
    upstream dbg2 {
        server 10.201.0.27:8888;
        keepalive 100;
        keepalive_requests 30000;
        keepalive_timeout 300s;
    }
    ...
}

设置 tcp 连接上跑了 30000 个 http 请求或者空闲 300s,那么就关闭连接。

之后继续测试,没有发现丢包。

从一起丢包故障来谈谈 nginx 中的 tcp keep-alive

序号 938:空闲 5 分钟后,nginx 主动发起 FIN 报文,关闭连接。


以上所述就是小编给大家介绍的《从一起丢包故障来谈谈 nginx 中的 tcp keep-alive》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

机器学习

机器学习

周志华 / 清华大学出版社 / 2016-1-1 / 88.00元

机器学习是计算机科学与人工智能的重要分支领域. 本书作为该领域的入门教材,在内容上尽可能涵盖机器学习基础知识的各方面。 为了使尽可能多的读者通过本书对机器学习有所了解, 作者试图尽可能少地使用数学知识. 然而, 少量的概率、统计、代数、优化、逻辑知识似乎不可避免. 因此, 本书更适合大学三年级以上的理工科本科生和研究生, 以及具有类似背景的对机器学 习感兴趣的人士. 为方便读者, 本书附录给出了一......一起来看看 《机器学习》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具

html转js在线工具
html转js在线工具

html转js在线工具