重新加载新的Nginxconfiguration,无需停机

我有一个Nginx服务器,不断处理高负载的请求。 我希望能够改变服务器的configuration文件并以零停机时间dynamic重新加载它。

我在shell中运行以下行:

httperf --server=127.0.0.1 --port=80 --uri=/ --num-conns=1 --num-calls=10 

而当它发送请求我重新加载我的nginxconfiguration。 我已经尝试了以下两个选项:

 sudo nginx -s reload sudo kill -s HUP [pid] 

它们都会导致httperf返回一些错误。 平均而言,在两个好的请求之后,httperf退出并打印它的日志,并附有以下相关的行:

 Errors: total 1 client-timo 0 socket-timo 0 connrefused 0 connreset 1 

我已经在许多地方看到,重装应该是无缝完成的,没有停机时间,但从testing中我看起来不一样。

我的问题是:

  1. 我是否以错误的方式进行testing? 为什么我得到这个连接重置?
  2. 有没有解决这个问题?
  3. 我实际上需要一个负载平衡器,我可以dynamic地添加和删除服务器,任何更好的解决scheme,适合我的问题?

在此先感谢帮助,期待看到一些有见地的答案。

要了解以下答案,需要一些背景:

  • 什么是HTTP持久连接 。
  • TCP协议的基础知识,特别是连接终止工作stream程。

我是否以错误的方式进行testing?

是的,你的testing有些不正确。 问题是你的testing使用PERSISTENT连接来发送10个请求。 您可以通过运行以下testing轻松检查它,并且不会有任何连接重置(因为每个连接只发送一个请求):

 httperf --server=127.0.0.1 --port=80 --uri=/ --num-conns=10 --num-calls=1 

为什么我得到这个连接重置?

如果你看看nginx的文档 ,你会发现这个:

旧工作进程接收到一个closures命令,停止接受新的连接,并继续服务当前的请求,直到所有这样的请求被服务。 之后,老员工stream程退出。

这是真的,但文档没有提到持续连接发生了什么。 我在旧的邮件列表中find答案。 在当前运行的请求被服务之后,nginx会通过向客户端发送[FIN, ACK]来发起closures持久连接。

为了检查,我使用WireShark和configuration服务器与一个简单的工人,请求睡5秒,然后回复。 我用下面的命令发送请求:

 httperf --server=127.0.0.1 --port=80 --uri=/ --num-conns=1 --num-calls=2 

发布前面提到的命令后,我重新加载nginx(当它处理第一个请求)。 这里是由WireShark嗅探的包:

wireshark流量

  • 3892-3894 – 通常的TCP连接build立。
  • 3895 – 客户端发送第一个请求。
  • 3896 – 服务器确认3895。
  • 这里nginx reload被执行了。
  • 4089 – 服务器发送响应。
  • 4090 – 服务器发送closures连接信号。
  • 4091 – 客户端确认4089。
  • 4092 – 客户确认4090。
  • 4093 – 客户端发送第二个请求( WTF?
  • 4094 – 客户端发送closures连接信号。
  • 4095 – 服务器确认4093。
  • 4096 – 服务器确认4094。

这是okey,该服务器没有发送任何响应第二个请求。 根据TCP连接终止 :

已经终止的一方不能再发送任何数据到连接,但另一方可以。 terminal方应继续读取数据,直到另一方终止。

接下来的问题是客户端收到来自服务器的紧密连接信号后,为什么会发生4093?

可能这是答案 :

我要说的是POST与FIN同时发生,即客户端发送POST,因为它的TCP堆栈没有处理来自服务器的FIN。 请注意,数据包捕获是在系统处理数据之前完成的。

我不能评论这一点,因为我不是networking专家。 也许其他人可以给出更有见地的答案,为什么第二个请求被发送。

UPD以前链接的问题是不相关的。 询问有关问题的单独问题。

有没有解决这个问题?

正如邮件列表中提到的那样:

HTTP / 1.1客户端需要处理keepalive连接closures,所以这不应该是一个问题。

我认为应该在客户端处理。 如果连接被服务器closures,客户端应该打开新的连接并重试请求。

我实际上需要一个负载平衡器,我可以dynamic地添加和删除服务器,任何更好的解决scheme,适合我的问题?

我不知道其他服务器,所以不能在这里build议。

只要你的客户可以正确处理连接,应该没有任何理由阻止你使用nginx。