我是第一次使用 HAProxy 来平衡我的应用程序,它目前运行五个后端应用程序实例。我的设置相对简单。我有一个 Ruby 应用程序,它使用 fiber、EventMachine 和 thin 来尽量保持其无阻塞。因此大多数请求都会快速返回,或者至少不会阻塞应用程序服务器,因此它可以同时处理多个请求。
但是,有些请求(例如需要访问 shell 命令的图像上传)可能会很慢并阻塞应用程序服务器。
我发现直接采用循环方式进行平衡在这里毫无意义,因为可以同时处理并快速返回的请求会滞后于缓慢的请求。处理这种情况的最佳方法是什么?
我考虑过:
进行频繁运行的健康检查(例如每 250 毫秒一次)以检查服务器是否响应。如果没有响应,则假设它处于“关闭”状态(很可能是阻塞长请求),这将导致 HAProxy 绕过它路由请求。但是在这种情况下,所有 5 个实例都可能被阻塞。
预先定义慢速请求 URL 列表,指定 2 或 3 个应用程序后端仅处理慢速请求,并将所有其他请求路由到“快速”后端。理论上,快速请求永远不会被阻止,但这种方法似乎有点不可靠,因为我需要确保如果 URL 发生变化,我会记得更新我的 HAProxy 配置。
我认为后一种方法可能是最好的,但由于 devops 不是我的强项,所以我想我会检查一下这种情况下最佳实践是什么。
当然,“最佳实践”可能是将所有长时间运行的请求移至后台任务,但在这种情况下,如果可以避免的话,我们假设我现在没有时间这样做:-)
答案1
来自 A 列的一点,来自 B 列的一点 :)
为了正常运行时间,无论如何,您都应该在 HAProxy 中使用健康检查。如果您的一个后端节点发生故障,您希望 HAProxy 停止向其发送请求。故障不一定发生在您的应用程序中,可能是硬件、网络或其他原因。配置起来非常简单:
option httpchk GET /test HTTP/1.0\r\n
250 毫秒听起来像是一个非常频繁的检查。按照这个速率,您的后端服务器可能要花费大量时间处理健康检查。您需要在应用程序开销与您希望死节点下线的速度之间权衡健康检查的成本。
第二种策略是我以前用过的。确定应用程序可以处理的并发连接总数。然后在 HAProxy 中,将请求分为慢速请求和快速请求,并为每个请求分配一定比例的总连接数。例如,
frontend myfrontend
bind *:80
acl url-slow path /some-long-running-request
use_backend slow-backend if url-slow
default_backend regular-backend
backend slow-backend
...
server backend1 1.2.3.4:80 maxconn 10
backend regular-backend
...
server backend1 1.2.3.4.:80 maxconn 90
因此,假设 backend1 可以处理 100 个并发连接。在上面,我们为“常规”请求分配 90 个连接,为运行缓慢的请求分配 10 个连接。即使您用完了所有慢速连接,仍会处理“常规”请求。
祝你好运!