我正在尝试在分叉服务器中使用Aerospike DB。我的群集由6个节点组成。我使用python客户端,但这不重要。
首先我创建了客户端,连接了它,而不是我分叉服务器。当集群状态发生变化(节点死亡)时,此解决方案存在问题,连接返回True
is_connected()
,但不能成功执行读取或写入操作。在这个解决方案中,每个节点有大约700个连接,这对集群来说是可以的。
我的第二次尝试是创建客户端,而不是分叉服务器并连接每个fork。此解决方案正确处理群集更改,但我必须为每个节点提供大约7k连接,这会导致节点不稳定。
如何更好地解决这个问题?
答案 0 :(得分:2)
在Python中,每个进程都需要有自己的客户端连接到服务器。如你所知,在分叉后你应该关闭并重新打开连接。
我猜你正在遇到CLOSE_WAIT
的问题。对于使用Java,C#,C等编写的长期运行的应用程序,这些应用程序连接到群集,并继续运行并向其发送操作。对于服务器上下文中的大多数动态语言,它们被设计为接受有限数量的请求然后终止,一些流程管理器不断地分支新流程。这对于WSGI背后的Python应用程序,Apache内部的PHP(mod_php)或者fastCGI(PHP-FPM),后面的乘客等的Ruby应用程序等都很常见。每次进程终止时,它使用的套接字在一段时间内都不可用(通常为4分钟)。由于流程配置为接受少量请求,您将看到CLOSE_WAIT
中的连接中断。
解决方案是让每个进程尽可能多地处理请求。我会监视您的应用程序进程,看看它们的大小是否保持稳定,只要没有内存泄漏膨胀,找到正确的更高的最大请求数。 PHP中的类似情况与过时的服务器配置建议有关,这些建议表明每个进程有几百个请求。 PHP在内存使用方面更稳定,这是一个无效的假设并且会损害性能,并且具有您描述的副作用。由于Python和PHP客户端每秒可以处理数千个(在最新测试中每个进程约4.5Ktps)请求,因此最大请求限制为500意味着该进程在高峰时段会在几分之一秒内被终止。 / p>
答案 1 :(得分:0)
我们更仔细地研究了这个问题,并且我们发现每个进程都不需要拥有自己的客户端连接。
使用分叉时,必须使用共享内存(shm)。 工作示例如下所示: https://gist.github.com/tivvit/c3652fdb6208752188fc
Shm是必不可少的,因为在这种模式下,父进程(创建连接的进程)会生成服务线程,该线程会使连接中的集群状态保持实际状态。
如果shm被省略,则没有人保持群集的状态。当集群状态发生变化(节点死亡)时,进程正在使用与旧集群设置的连接,从而导致连接超时和其他问题。
另一个明显的问题是你必须保持父进程的生存。如果父进程被终止,则服务线程也将被终止。所以你必须记住,在连接到集群之前必须发生进程守护进程。
也许这应该在文档中提及?