我正在尝试使用use-server
规则将多个后端块合并为一个。我有多个 URL 路径的请求,这些请求webadmin.example.org
都指向同一个后端,并且我试图让这些请求根据 URL 路径发送到不同的服务器。它部分工作正常,但在某些情况下会失败。Ubuntu 18.04 上的 Haproxy 1.8.8。这是我的配置:
backend webadmin
# Tried both of these; it balances between servers otherwise.
#balance source
balance hdr(host)
acl path:phpmyadmin path_beg -i /phpmyadmin
acl path:phppgadmin path_beg -i /phppgadmin
acl path:rabbitmq path_beg -i /rabbitmq
acl path:rcmdr path_beg -i /rediscommander
reqrep ^([^\ ]*\ /)rabbitmq[/]?(.*) \1\2 if path:rabbitmq
reqrep ^([^\ ]*\ /)rediscommander[/]?(.*) \1\2 if path:rcmdr
use-server rcmdr:00 if path:rcmdr
use-server rabbitmq:00 if path:rabbitmq
use-server nginx:00 if path:phpmyadmin || path:phppgadmin
# Tried these too.
#use-server rabbitmq:00 if { path_beg -i /rabbitmq }
#use-server nginx:00 if { path_beg -i /phpmyadmin } || { path_beg -i /phppgadmin }
#use-server rcmdr:00 if { path_beg -i /rediscommander }
server rabbitmq:00 localhost:15672 maxconn 10000 check fall 3 rise 2
server rcmdr:00 localhost:6670 maxconn 10000 check fall 3 rise 2
server nginx:00 localhost:6669 maxconn 10000 check fall 3 rise 2
我的经验是,对匹配的 ACL 的请求path:phpmyadmin
会path:phppgadmin
转到正确的服务器(Nginx,其中 URL 路径被排序到正确的应用程序),但对其他两个 ACL 的请求似乎忽略了规则use-server
,并且只转到规则列表中首先定义的服务器(或者如果使用循环平衡模式,则每个请求都会路由到不同的后端,而忽略规则use-server
)。
如果我删除reqrep
规则,每个请求都会根据规则正确路由use-server
。不幸的是,我需要这些规则,以便后端服务器正确响应请求(即,它们不应该看到子路径 URL,因为它们对它们一无所知,它们只是用于在 Haproxy 内路由)。
那么,我可以同时使用reqrep
&use-server
规则吗?如果可以,该如何使用?
答案1
好吧,我使用变量构建了一些对我有用的东西。正如@Michael - sqlbot提到的,我假设ACL类似于传递值变量,这样您可以将值存储在那里并使用它们,即使值的来源发生变化。我不知道Haproxy有一个set-var
功能。我也查看了Lua选项,但选择了这个,因为它可以完成我需要它做的事情。
frontend public
# ... bind, basic setup, etc.
# ACLS by request path.
acl path:rcmdr path_reg ^/rediscommander(/.*)?$
acl path:rabbitmq path_reg ^/rabbitmq(/.*)?$
# Set the variables here.
http-request set-var(txn.rcmdr) bool(true) if path:rcmdr
http-request set-var(txn.rabbitmq) bool(true) if path:rabbitmq
acl dom:webadmin hdr_dom(host) -i webadmin.example.org
use_backend webadmin if dom:webadmin
backend webadmin
balance hdr(host)
acl path:phpmyadmin path_beg -i /phpmyadmin
acl path:phppgadmin path_beg -i /phppgadmin
# Set the ACL if the variable was set in the frontend.
acl path:rabbitmq var(txn.rabbitmq),bool
acl path:rcmdr var(txn.rcmdr),bool
use-server rcmdr if path:rcmdr
use-server rabbitmq if path:rabbitmq
use-server nginx if path:phpmyadmin || path:phppgadmin
# reqrep doesn't kill our ACLs because they are set based on boolean variables
# from the frontend, not from mutable request paths tested in the backend.
reqrep ^([^\ ]*\ /)rabbitmq[/]?(.*) \1\2
reqrep ^([^\ ]*\ /)rediscommander[/]?(.*) \1\2
server rabbitmq localhost:15672 maxconn 10000 check fall 3 rise 2
server rcmdr localhost:6670 maxconn 10000 check fall 3 rise 2
server nginx localhost:6669 maxconn 10000 check fall 3 rise 2