zoukankan      html  css  js  c++  java
  • Nginx

    目录

    - 1. 前言
    - 2. keepalive 介绍
    - 3. Nginx 与 keepalive 的关系
        - 3.1 Nginx - keepalive_timeout
        - 3.2 Nginx - keepalive_requests
        - 3.3 Nginx - upstream - keepalive

    1. 前言

    在 nginx中,有三处配置会涉及到 keepalive 的配置:

    1. http配置段的 keepalive_timeout 项
    2. http配置段的 keepalive_request 项
    3. upstream 代码段的 keepalive 项

    2. keepalive 介绍

    什么是 keepalive?作用是什么?

    keepalive 是在 TCP 中一个可以检测死连接的机制,作用是保持 socket 长连接不被断开,属于 TCP 层的功能,并不属于应用层。

    TCP 层怎么做到保持长连接的?

    Linxu 中有三个参数,开发给应用层使用:

    net.ipv4.tcp_keepalive_intvl = 75   探测间隔,未收到回复时,重试的时间间隔,单位:秒
    net.ipv4.tcp_keepalive_probes = 9   探测次数,重试次数
    net.ipv4.tcp_keepalive_time = 7200  探测的心跳间隔,TCP链接在多少秒之后没有数据报文传输启动探测报文,单位:秒

    3. Nginx 与 keepalive 的关系

    3.1 Nginx - keepalive_timeout

    在 nginx http配置段有 keepalive_timeout 配置项,默认为 65 秒

    keepalive_timeout 65; 服务器端主动发起keepalive连接,并保持 65 秒,如果超过65秒没有发送任何请求,则服务器主动断开连接,TCP从ESTABLISHED 转为 TIME_WAIT 状态。

    为什么会用到 keepalive_timeout ?

    通过配置 keepalive_timeout 可以实现服务器与客户端之间的长连接,用户连接访问服务器可能不止 1 次请求,使用keepalive可以减少系统对TCP连接的建立和销毁的开销。

    接下来通过抓包来验证 开启 和 关闭 keepalive_timeout 的两种情况:

    (1)测试1 - 配置 keepalive_timeout 为 0

    192.168.118.15:nginx服务器
    192.168.118.94:客户端

    配置如下:

    抓包分析:

    当设置 keepalive_timeout 0 时,用户发起一个请求,创建一个TCP连接,完成请求后,nginx端主动发送 FIN 断开,从ESTABLISHED 转为 TIME_WAIT 当第二个请求再来时,重复以上步骤。

    在创建和销毁TCP连接的同时,会消耗系统资源。在高并发的时候,会造成大量系统资源的浪费,产生很多 TIME_WAIT 连接占用端口,如果不能及时的断开,则会造成系统端口用尽的情况。

    当设置 keepalive_timeout 0 时,通过浏览器快速刷新,查看nginx服务器连接数:

    可以看到, 充斥着大量的 TIME_WAIT 状态的tcp连接,这只截了一部分。

    (2)测试2 - 配置 keepalive_timeout 65

     首先,从时间上分析下keepalive 保活,从上图看, TCP Keep-Alive 是 10 秒中,没有任何数据传输才会触发 keepalive保活机制。

    在从这张图来看,在 nginx 中,keepalive_timeout 的解释应该是:如果 65 秒中之内,没有接收到任何数据,则主动断开,如果在65秒内有数据传输,则从最后一次数据传输完毕后,重置计时时间。

    从 TCP 追踪流来看

    在 keepalive_timeout 时间内的请求, 都由一个 TCP 连接进行处理了,TCP连接得到很好的复用,减少了系统的开销。

    当设置 keepalive_timeout 65 时,通过浏览器快速刷新,查看nginx服务器连接数:

    可以看到, 对于一个客户端,只需要开启一个tcp连接请求就能轻松实现请求处理,大大减低了资源的浪费。

    总结:

    对于nginx来说,开启 keepalive_timeout 还是很有必要的,通过测试也得知,keepalive_timeout 是从最后一个请求开始计时,对于高并发的主机来说,这个时间可以适当的进行调整。

    3.2 Nginx - keepalive_requests

    keepalive_requests指令用于设置一个keep-alive连接上可以服务的请求的最大数量,当最大请求数量达到时,连接被关闭,值为0会也禁用keep-alive客户端连接;。默认是100。

    答案显而易见,通过 keepalive_timeout keepalive_requests 来管理长连接:

    •   当一个tcp连接存活时间超过 keepalive_timeout 时则会被close掉,nginx的具体实现,是通过定时器来做的
    •   当一个tcp连接最大数超过 keepalive_requests 时则也会被close掉

    (1)测试1 - keepalive_requests 为 0

     

    抓包分析如下:

     当 keepalive_requests 为 0 的时候,keepalive 的关闭的状态,1个TCP连接处理1个请求。和keepalive_timeout 为 0 一样的效果。因此要开启keepalive时,这两个参数都不能为0

    (2)测试-2 - keepalive_requests 为 3

     

    抓包分析如下:

    当设置 keepalive_requests 为 3 时,一个TCP 连接最多响应用户请求 3 次就强制断开连接,不会等到 keepalive_timeout 时间后断开。

    总结:

        keepalive_requests 就等于是设置 一个 TCP 连接的处理请求的数量,当请求等于设定的这个数值,就断开该连接,如果用户再次发起连接则新建一个TCP连接响应用户。

    3.3 Nginx - upstream - keepalive

     为了测试 upstream 中的 keepalive 的功能,后端服务器采用 tomcat

     主机信息:

    客户端     192.168.118.94
    nginx     192.168.118.15
    tomcat    192.168.118.16

     在 http 1.1 中可以配置服务器端开启 keepalive 与客户端保持长连接。接下来看 nginx与后端服务器怎样交互的。

    nginx 配置如下:

    keepalive_timeout:65 设置nginx开启keepalive,超时时间为65秒,也就是说:如果客户端65秒内没有后续的请求过来,nginx就会断掉这个TCP连接,设置为0表示禁用keepalive。
    keepalive_requests :100 设置长连接能够处理请求的次数,100表示:一个长连接nginx最多处理100次请求就会关闭。

    这两个配置项,上面已经得到了证实。

    keepalive : 10 这个值必须设置,默认为0. 设置每个worker可以保持长连接空闲时的最大连接数。

    这里需要特别解释一下,假设nginx有100个请求需要访问Tomcat,那么会建立100个连接,如果双方都支持keepalive,那么这100个连接都是长连接(可以复用那种的),当请求结束后,nginx会立马销毁 90个(100-90),只剩下10个长连接,这10个长连接在Tomcat的keepAliveTimeout时间到期后由Tomcat方关闭。

    Tomcat的 keepAliveTimeout这个值可以设置大一些,性能会很好,比如设置个10分钟,20分钟的。

    测试

    用户端用浏览器快速的刷新,首先查看 nginx 连接情况:

    可以看到火狐浏览器启动了 5 个tcp连接来加载资源,无论怎么刷新,连接都不会变化,这就是因为使用了 keepalive,所有的连接可以进行复用,如果把 nginx 的keepalive_timeout 设置为 0 ,每次刷新都会使用新的 TCP 连接,这里会出现大量的 TIME_WAIT 的连接。

    接下来,查看 tomcat 服务器连接情况:

    只截图了一部分,出现了大量的 TIME_WAIT 的 tcp 连接,也就是说 客户端与 nginx 连接时确实是用了keepalive,但是nginx与tomcat的连接却没有启用keepalive,每一次请求都新建一个 tcp,用完一次就关闭没有复用,所以出现了大量的TIME_WAIT的TCP连接,如果流量稍微大一些tomcat服务器会因为tcp资源耗尽而宕机。

    通过上面的配置,在 upstream 中,已经配置过 keepalive,为什么没有生效呢?

    这里就需要抓包分析 nginx 与 tomcat 之间是不是依然采用的http1.0 短连接通信:

    客户端连接nginx时,使用的 http1.1,并设置了 keepalive 头

    而 nginx 请求tomcat时,采用的是 http1.0,并且 connection 设置了 close 告诉 tomcat 连接只用一次,用完关闭。

    通过上面分析,很明确的知道了 nginx 到 tomcat 采用的是 http1.0 短连接模式。查看官方:

    需要在 location 中配置:

    proxy_http_version 1.1;
    proxy_set_header Connection "";

    现在 nginx 到后端的连接也是 http1.1

    接下来,还是通过浏览器刷新,查看服务器连接状态:

    nginx 服务器查看如下:

     一共 10 个连接, 其中 5 个是 客户端与 nginx 的连接,另外 5 个是nginx与tomcat的连接。

    再次查看 tomcat 服务器连接状态:

    tomcat 上一共是 5 个与 nginx 服务器的连接。这样 nginx 与 tomcat 也是 keepalive 长连接了。

    这里在补充下,经过测试,nginx 与 后端 tomcat 断开是由 tomcat 中 connectionTimeout 决定的,而且是由后端tomcat 主动断开连接。

  • 相关阅读:
    Flume 读取实时更新的日志文件
    一些关于Flume收集日志的资料
    Java Pattern Matcher 正则表达式需要转义的字符
    多播 & multicast
    branch prediction
    一时紧张简单题都没做好,哈
    海量数据求中位数
    继续过Hard题目.0207
    压力工具代码及epoll使用
    C++里面mutable的作用
  • 原文地址:https://www.cnblogs.com/hukey/p/10506556.html
Copyright © 2011-2022 走看看