我有两个服务器监听一个负载均衡器后面的TCP端口。负载均衡器可以检测来自客户端的TCP连接尝试是否失败,并在不删除该连接的情况下将其重试到第二台服务器。我希望能够将这两台服务器中的任何一台进行维护,而不需要删除一个客户端集合。
我的服务器使用此代码处理客户端请求:
ServerSocketFactory ssf = ...
ServerSocket serverSocket = ssf.createServerSocket(60000);
try {
while (true) {
Socket socket = serverSocket.accept();
...// Do the processing
}
} catch (IOException e) {
...
}
...我最初的想法是添加一个布尔值,该布尔值将在应用程序关闭时设置,并在等待所有现有连接被处理和关闭时阻止新的serverSocket.accept()调用。但是,甚至在serverSocket.accept()调用之前就已经建立了新的连接。这是我在Wireshark上看到的,如果我在呼叫之前放置一个断点。

问题在于,当我调用serverSocket.close()时,所有这样的客户端连接都会被删除。我想要实现的是告诉ServerSocket停止接受所有新连接(即只发送新连接的RST或让它们超时),这样负载均衡器可以将它们重新路由到另一个服务器,但同时不丢弃任何已经建立的连接。
编辑:,我正在寻找一些自动化的解决方案,它不会要求我每次更新应用程序时都更改任何负载均衡器或操作系统设置。
发布于 2017-06-12 23:11:03
您可以在服务器上添加防火墙规则,这将阻止新的连接,但使旧连接保持活动状态。我想服务器是基于Linux的?如果是这样的话,您可以尝试:
iptables -A INPUT -p tcp --syn --destination-port <port> -j REJECT --reject-with icmp-host-prohibited在此之后,您可以检查netstat,是否存在任何活动连接,并在没有任何连接的情况下将应用程序关闭一次:
netstat -ant|grep <port>|grep EST在您完成维护之后,可以删除防火墙规则。首先,列出查找它的所有规则:
iptables -L -n并移除:
iptables -D INPUT <rule number>发布于 2017-06-13 02:00:27
在ServerSocket.accept()块或ServerSocketChannel.accept()返回null的任何时候,待办事项队列都是空的。此时,停止接受并关闭侦听套接字。等待所有现有的可接受套接字完成它们的工作,然后让应用程序在此时退出。
发布于 2017-06-17 20:07:21
解决问题的最简单方法是将附加的负载均衡器放在本地的应用服务器之前。
检查nginx和HAproxy并对它们进行选择,这对您的任务更好。它们都有一个优雅关闭的特性,这意味着它们不再接受新的连接,而是继续提供服务直到结束。另一个优点是您的应用程序不需要对代码进行任何更改。
nginx的优美关机
nginx -s quitHAproxy的优美关机
haproxy -sf $(cat /var/run/haproxy.pid)https://stackoverflow.com/questions/44464617
复制相似问题