From: Willy Tarreau Date: Thu, 26 Jun 2025 13:29:47 +0000 (+0200) Subject: MEDIUM: proxy: mark the "dispatch" directive as deprecated X-Git-Tag: v3.3-dev2~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5c15ba5eff5f110a5151f04fa4ea7d196a0e2229;p=thirdparty%2Fhaproxy.git MEDIUM: proxy: mark the "dispatch" directive as deprecated As mentioned in [1], the "dispatch" directive from haproxy 1.0 has long outlived its original purpose and still suffers from a number of technical limitations (no checks, no SSL, no idle connes etc) and still hinders some internal evolutions. It's now time to mark it as deprecated, and to remove it in 3.5 [2]. It was already recommended against in the documentation but remained popular in raw TCP environments for being shorter to write. The directive will now cause a warning to be emitted, suggesting an alternate method involving "server". The warning can be shut using "expose-deprecated-directives". The rare configs from 1.0 where "dispatch" is combined with sticky servers using cookies will just need to set these servers's weights to zero to prevent them from being selected by the load balancing algorithm. All of this is explained in the doc with examples. Two reg tests were using this method, one purposely for this directive, which now has expose-deprecated-directives, and another one to test the behavior of idle connections, which was updated to use "server" and extended to test both "http-reuse never" and "http-reuse always". [1] https://github.com/orgs/haproxy/discussions/2921 [2] https://github.com/haproxy/wiki/wiki/Breaking-changes --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 644db57a2..c5d20e697 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -5474,7 +5474,7 @@ default-server X - X X default_backend X X X - description - X X X disabled X X X X -dispatch - - X X +dispatch (deprecated) - - X X email-alert from X X X X email-alert level X X X X email-alert mailers X X X X @@ -6818,7 +6818,7 @@ disabled See also : "enabled" -dispatch
: +dispatch
: (deprecated) Set a default server address May be used in the following contexts: tcp, http @@ -6842,6 +6842,27 @@ dispatch
: syntax, it has also been used for simple TCP relays. It is recommended not to use it for more clarity, and to use the "server" directive instead. + This keyword has been deprecated in 3.3 and will be removed in 3.5 due to + some internal limitations (no support for SSL nor idle connections etc). + Using it will emit a warning that may be silenced by enabling directive + "expose-deprecated-directives" in the global section. + + The correct way to proceed without this directive is to simply declare a + server with the same address and port. If the "dispatch" directive was + mixed with other servers, then these servers should be configured with a + weight of zero in order never to be elected by the load balancing algorithm. + + Example: + backend deprecated_setup + dispatch 192.168.100.100:80 # external load balancer's address + server s1 192.168.100.1:80 cookie S1 check + server s2 192.168.100.2:80 cookie S2 check + + backend modern_setup + server external_lb 192.168.100.100:80 + server s1 192.168.100.1:80 cookie S1 check weight 0 + server s2 192.168.100.2:80 cookie S2 check weight 0 + See also : "server" diff --git a/reg-tests/connection/dispatch.vtc b/reg-tests/connection/dispatch.vtc index 8696b506e..16151a188 100644 --- a/reg-tests/connection/dispatch.vtc +++ b/reg-tests/connection/dispatch.vtc @@ -12,6 +12,10 @@ server s2 { } -start haproxy h1 -conf { +global + # this is needed since 3.3, and this test will be removed in 3.5. + expose-deprecated-directives + defaults log global timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" diff --git a/reg-tests/connection/http_reuse_dispatch.vtc b/reg-tests/connection/http_reuse_dispatch.vtc index 56fbce319..50f804bee 100644 --- a/reg-tests/connection/http_reuse_dispatch.vtc +++ b/reg-tests/connection/http_reuse_dispatch.vtc @@ -7,16 +7,26 @@ varnishtest "Test the proper interaction between http-reuse and dispatch mode" feature ignore_unknown_macro haproxy h1 -conf { + global + nbthread 1 + defaults timeout client 30s timeout server 30s timeout connect 30s mode http - listen sender - bind "fd@${feS}" + listen sender1 + bind "fd@${feN}" + http-reuse never + http-request set-header client-id %[req.hdr(client-id)] if { req.hdr(client-id) -m found } + server dispatch ${h1_feR_addr}:${h1_feR_port} + + listen sender2 + bind "fd@${feA}" + http-reuse always http-request set-header client-id %[req.hdr(client-id)] if { req.hdr(client-id) -m found } - dispatch ${h1_feR_addr}:${h1_feR_port} + server dispatch ${h1_feR_addr}:${h1_feR_port} listen receiver bind "fd@${feR}" @@ -26,7 +36,8 @@ haproxy h1 -conf { http-after-response set-header client-id %[var(sess.client_id)] } -start -client c1 -connect ${h1_feS_sock} { +### http-reuse never +client c1 -connect ${h1_feN_sock} { txreq \ -hdr "client-id: c1" rxresp @@ -43,7 +54,7 @@ client c1 -connect ${h1_feS_sock} { expect resp.http.client-id == "c1" } -run -client c2 -connect ${h1_feS_sock} { +client c2 -connect ${h1_feN_sock} { txreq \ -hdr "client-id: c2" rxresp @@ -61,7 +72,7 @@ client c2 -connect ${h1_feS_sock} { expect resp.http.client-id == "c2" } -run -client c3 -connect ${h1_feS_sock} { +client c3 -connect ${h1_feN_sock} { txreq \ -hdr "client-id: c3" rxresp @@ -78,3 +89,57 @@ client c3 -connect ${h1_feS_sock} { expect resp.http.http_first_request == "0" expect resp.http.client-id == "c3" } -run + +### http-reuse always +client c4 -connect ${h1_feA_sock} { + txreq \ + -hdr "client-id: c4" + rxresp + expect resp.http.http_first_request == "1" + + txreq + rxresp + expect resp.http.http_first_request == "0" + expect resp.http.client-id == "c4" + + txreq + rxresp + expect resp.http.http_first_request == "0" + expect resp.http.client-id == "c4" +} -run + +client c5 -connect ${h1_feA_sock} { + txreq \ + -hdr "client-id: c5" + rxresp + expect resp.http.http_first_request == "0" + expect resp.http.client-id == "c5" + + txreq + rxresp + expect resp.http.http_first_request == "0" + expect resp.http.client-id == "c5" + + txreq + rxresp + expect resp.http.http_first_request == "0" + expect resp.http.client-id == "c5" +} -run + +client c6 -connect ${h1_feA_sock} { + txreq \ + -hdr "client-id: c6" + rxresp + expect resp.http.http_first_request == "0" + expect resp.http.client-id == "c6" + + txreq + rxresp + expect resp.http.http_first_request == "0" + expect resp.http.client-id == "c6" + + txreq + rxresp + expect resp.http.http_first_request == "0" + expect resp.http.client-id == "c6" +} -run diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index 62b79f388..eaf07379a 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -2664,6 +2664,18 @@ stats_error_parsing: if (alertif_too_many_args(1, file, linenum, args, &err_code)) goto out; + if (!deprecated_directives_allowed) { + ha_warning("parsing [%s:%d]: '%s' is deprecated in 3.3 and will be removed in 3.5. " + "The modern way to do the same is to create a server with the same address, and " + "possibly to assign any extra server a weight of zero if any:\n" + " server dispatch %s\n" + "Note that it is still possible to silence this warning by setting " + "'expose-deprecated-directives' in the 'global' section, but do not wait to fix " + "your configuration!\n", + file, linenum, args[0], args[1]); + err_code |= ERR_WARN; + } + curproxy->dispatch_addr = *sk; curproxy->options |= PR_O_DISPATCH; }