我在 CentOS 7 上运行 haproxy 1.5.18-3,需要使用 stick-table 功能来确保特定用户的流量持续到给定的服务器。
当连接缓慢时,一切工作正常,然而当有大量同时连接并且尚不存在粘表条目时,某些请求将被发送到两个后端服务器,直到它们最终只粘在一个服务器上。
例如,像这样使用 Apache Bench:
ab -c 10 -n 30 'http://example.com/[email protected]'
我在 haproxy 日志中看到这一点:
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50812 [08/May/2017:14:49:10.934] http_front backend/server-1 0/0/0/7/7 200 222 - - ---- 9/9/9/4/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50811 [08/May/2017:14:49:10.933] http_front backend/server-2 0/0/0/8/8 200 222 - - ---- 8/8/8/4/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50816 [08/May/2017:14:49:10.935] http_front backend/server-1 0/0/0/7/7 200 222 - - ---- 7/7/7/1/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50819 [08/May/2017:14:49:10.935] http_front backend/server-2 0/0/1/6/7 200 222 - - ---- 6/6/6/1/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50814 [08/May/2017:14:49:10.935] http_front backend/server-1 0/0/0/7/7 200 222 - - ---- 5/5/5/1/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50810 [08/May/2017:14:49:10.933] http_front backend/server-1 0/0/0/9/9 200 222 - - ---- 4/4/4/0/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50813 [08/May/2017:14:49:10.934] http_front backend/server-2 0/0/0/8/8 200 222 - - ---- 3/3/3/0/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50815 [08/May/2017:14:49:10.935] http_front backend/server-2 0/0/0/7/7 200 222 - - ---- 2/2/2/0/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50817 [08/May/2017:14:49:10.935] http_front backend/server-2 0/0/0/7/8 200 222 - - ---- 1/1/1/0/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50818 [08/May/2017:14:49:10.935] http_front backend/server-1 0/0/1/6/8 200 222 - - ---- 0/0/0/0/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50820 [08/May/2017:14:49:10.967] http_front backend/server-1 0/0/0/5/5 200 222 - - ---- 3/3/2/2/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50821 [08/May/2017:14:49:10.968] http_front backend/server-1 0/0/0/4/4 200 222 - - ---- 2/2/2/2/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50823 [08/May/2017:14:49:10.972] http_front backend/server-1 0/0/1/5/6 200 222 - - ---- 7/7/7/7/0 0/0 "GET /[email protected] HTTP/1.0"
May 8 14:49:10 localhost haproxy[4996]: 1.2.3.4:50822 [08/May/2017:14:49:10.972] http_front backend/server-1 0/0/0/8/8 200 222 - - ---- 6/6/6/6/0 0/0 "GET /[email protected] HTTP/1.0"
[...]
此后,haproxy 正确地将所有流量发送到 server-1。当 stick-table 条目过期时,问题再次出现。
我尝试保留 url 参数和源地址,但都出现同样的问题。
haproxy 无法正确处理大量此类同时 (并发) 请求吗?我能做些什么让它按预期工作吗?
谢谢。
答案1
实际情况是,在 HAProxy 创建 stick-table 条目之前,它需要验证第一个连接是否成功,然后再创建该条目。由于有如此多的请求彼此接近,它没有时间验证它是否有效,因此在此之前它将平衡后端服务器之间的连接。
我能做些什么让它按预期工作?
我最终使用了 url_param 平衡算法并将其设置为使用 email 参数。
balance url_param email
HAProxy 获取 url_param 的值,对其进行哈希处理,然后确定将其发送到哪个后端服务器,并始终将其发送到那里,至少直到后端服务器发生变化(例如添加节点)。此时,可以使用 stick-tables 来帮助避免后端发生变化时流量被错误路由。