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