我正在尝试设置Haproxy来对由uri路径标识的几个后端进行负载均衡请求。例如:
应该导致“catalog-v1”后端。
事情是每个应用程序在不同的路径上响应所以我不仅要识别应用程序,还要重写URL路径。 E.g。
要
我知道我不应该使用Haproxy进行重写,但现在这是不可避免的。
尝试使用regex101的以下正则表达式:
([a-z.]*)\/([a-z0-9\-\.]*)\/([a-z\-]*)\/(.*)
换人:
\1/\3-\2/\4
最后这里是haproxy.config:
global
daemon
user root
group root
maxconn 256000
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
stats socket /run/haproxy/stats.sock mode 777 level admin
defaults
log global
option dontlognull
maxconn 4000
retries 3
timeout connect 5s
timeout client 1m
timeout server 1m
option redispatch
balance roundrobin
listen stats :8088
mode http
stats enable
stats uri /haproxy
stats refresh 5s
backend catalog-v1
mode http
option httpchk GET /catalog-v1/ping
http-check expect status 200
reqrep ([a-z.]*)\/([a-z0-9\-\.]*)\/([a-z\-]*)\/(.*) \1/\3-\2/\4
server 127.0.0.1:8280_catalog-v1-node01 127.0.0.1:8280 check inter 2s rise 3 fall 2
backend checkout-v1
mode http
option httpchk GET /checkout-v1/ping
http-check expect status 200
reqrep ([a-z.]*)\/([a-z0-9\-\.]*)\/([a-z\-]*)\/(.*) \1/\3-\2/\4
server 127.0.0.1:8180_checkout-v1-node01 127.0.0.1:8180 check inter 2s rise 3 fall 2
frontend shared-frontend
mode http
bind localhost:80
acl is-catalog-v1-path path_dir /v1/catalog
acl is-checkout-v1-path path_dir /v1/checkout
use_backend catalog-v1 if is-catalog-v1-path
use_backend checkout-v1 if is-checkout-v1-path
我错过了什么吗?
我一直在努力解决这个问题很长一段时间没有成功。后端在Haproxy stats页面中显示“UP”,但每当我调用“non rewrited url”时,我都会收到400 Bad Request错误。
提前感谢您的帮助!
答案 0 :(得分:11)
如果我理解正确,请替换以下示例:
reqrep ^([^\ ]\*)\ /([-.0-9A-Za-z]\*)/([a-zA-Z]\*)/(.\*) \1\ /\3-\2/\4
http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#reqrep
reqrep search string [{if | unless} cond]
你没有空格。
答案 1 :(得分:5)
上面的答案是一个单一的修复,不能解释问题的根源。问题在于,当我们实际解析/重写HTTP头时,许多人认为我们正在解析完整的URL或仅解析PATH组件。
例如:
curl -iv https://stackoverflow.com/questions/24784517/haproxy-route-and-rewrite-based-on-uri-path
* Trying 151.101.65.69...
> GET /questions/24784517/haproxy-route-and-rewrite-based-on-uri-path HTTP/1.1
> Host: stackoverflow.com
> User-Agent: curl/7.54.0
> Accept: */*
目标是将GET /some_path HTTP/1.1
重写为GET /some_other_path HTTP/1.1
我想澄清上面的解决方案是有效的,因为它考虑了匹配和替换中的HTTP动词。 ^([^\ ]\*)\ (.*)
捕获动词并在替换模式中使用它。 \1 \2