我已经配置了一台具有 8 个核心的服务器,并计划部署网络服务。为了分散请求负载,我想运行 8 个服务实例。这没什么奇怪的。我无法访问硬件负载平衡器。我应该提到,我目前已分配了 5 个公共 IP 地址(但我可以获得更多)。
因此,我希望听听您对构建软件负载平衡解决方案的建议。
显而易见的选择是:
- 使用 HAProxy;或者
- 预先分叉我的应用程序(就像 Facebook Tornado 和 Unicorn 都做的那样);
- 在这里插入你的想法。
我的目标是:
- 在服务实例之间分散请求负载;
- 允许滚动重启我的服务(代码升级)。
我应该提到这不是基于 HTTP 的服务,所以 NGiNX 之类的服务不适用。
我不喜欢 HAProxy,因为它需要内存;它似乎要求每个客户端连接都有一个读写缓冲区。因此,我会在内核级别、HAProxy 和我的应用程序中设置缓冲区。这太愚蠢了!也许我在这方面忽略了什么?
谢谢!
答案1
无论采用哪种解决方案,如果您安装了一个进程来转发流数据,它将需要每个连接缓冲区。这是因为您无法始终发送所有收到的内容,因此您必须将多余的内容保存在缓冲区中。也就是说,内存使用量将取决于并发连接数。一个大型站点正在愉快地运行 haproxy,默认设置为 150000 个并发连接(4 GB RAM)。如果您需要更多,版本 1.4 允许您调整缓冲区大小而无需重新编译。但是,请记住,每个套接字的内核缓冲区永远不会低于每个方向和每个套接字 4kB,因此每个连接至少 16 kB。这意味着让 haproxy 以每个缓冲区少于 8 kB 的内存运行是没有意义的,因为它消耗的内存已经少于内核的内存。
此外,如果您的服务是纯 TCP 且代理没有附加价值,请查看基于网络的解决方案,例如 LVS。它便宜得多,因为它处理数据包并且不需要维护缓冲区,因此套接字缓冲区在已满时会丢弃数据包,并且可以与服务安装在同一台机器上。
编辑: Javier,依赖操作系统进行负载平衡的预分叉进程根本无法很好地扩展。操作系统唤醒每一个当它获得连接时,所有进程都会启动,但只有其中一个进程会获得连接,而其他所有进程都会再次进入休眠状态。多进程模式下的 Haproxy 在 4 个进程左右时性能最佳。当进程数达到 8 个时,性能已经开始下降。Apache 对此使用了一个很好的技巧,它在 accept() 周围进行锁定,以便只有一个进程在等待接受。但这会破坏操作系统的负载平衡功能,并停止在 1000 到 2000 个进程之间进行扩展。它应该使用一些锁的数组,以便唤醒一些进程,但它没有这样做。
答案2
由于没有关于您服务的任何详细信息,因此很难说;但一般来说,我倾向于预分叉。这是一个经过验证的服务器策略(而不是像某些人读过 tornado/unicorn 粉丝网站后认为的那样,是一种新奇的技巧)。
除此之外,还有一些提示:
每个预先分叉的进程可以使用现代非
select
策略(主要是 libevent)来处理大量客户端。核心和进程之间 1:1 的关系很少能带来最佳性能;通常最好对负载进行一些动态适应。