Setting max concurrent HTTP requests per frontend

Hello,

I have 2+ servers running on one VM, and I want to only process one HTTP request at a time across all of them (they’re performing brief, mem and CPU-intensive work).

Protect Servers with HAProxy Connection Limits and Queues - HAProxy Technologies says if mode http is set, “the maxconn parameter on a server line … relates to the number of concurrent HTTP requests.”

That’s close to what I need, but maxconn in frontend or global seems to mean connections, not requests.

Is there some way to achieve this? Thanks-


Two configs I’ve tried:

global
 	maxconn 1

frontend MyFrontend1
	bind	127.0.0.1:3001
	default_backend	rpc_1

backend rpc_1
   mode http
   server s1 127.0.0.1:31234

frontend MyFrontend2
	bind	127.0.0.1:3002
	default_backend	rpc_2

backend rpc_2
   mode http
   server s2 127.0.0.1:31235
frontend rpc
	mode http
	bind :3001
	bind :3002
	maxconn 1
	use_backend rpc_1 if { dst_port 3001 }
	use_backend rpc_2 if { dst_port 3002 }

Came up with this approach. The extra hop adds a noticeable amount of latency though.

# Funnel all requests through a single pipe ...
frontend Intake
	mode http
	bind :3001
	bind :3002
	http-request add-header x-forwarded-port %[dst_port]
	use_backend Layer1b

backend Layer1b
	mode http
	server sl1b 127.0.0.1:4000 maxconn 1

# ... and then re-route to different backends
frontend Route
	mode http
	bind :4000
	acl is3001 hdr(x-forwarded-port) -i 3001
	acl is3002 hdr(x-forwarded-port) -i 3002
	use_backend rpc_1 if is3001
	use_backend rpc_2 if is3002

backend rpc_1
	mode http
	server s1 127.0.0.1:31234 maxconn 2

backend rpc_2
	mode http
	server s2 127.0.0.1:31235 maxconn 2

I find that hard to believe. You said that a request causes mem and CPU intensive work, so this should be completely negligible.

Maybe you benchmarked with empty request, and therefore benchmarked basically connection setup time?

That said, I can think of another way in this particular case. You can adjust the destination port dynamically in the backend with set-dst-port [1] :

frontend fe_in
 bind :3001
 bind :3002
 use_backend be_out

backend be_out
 http-request set-dst-port int(31234) if { dst_port 3001 }
 http-request set-dst-port int(31235) if { dst_port 3002 }
 server s1 127.0.0.1:80 maxconn 1

The port specified in the server configuration really doesn’t matter then.

[1] HAProxy version 2.6.15-62 - Configuration Manual

Yes, I was benchmarking an empty response. It added 1-2 ms vs. a single transparent frontend+backend proxy, with 50 concurrent connections.

Thanks for the idea. That worked with minor changes (mode http and 0.0.0.0:0 in the server line) and got rid of the additional latency.

frontend fe_in
 mode http
 bind :3001
 bind :3002
 use_backend be_out

backend be_out
 mode http
 http-request set-dst-port int(31234) if { dst_port 3001 }
 http-request set-dst-port int(31235) if { dst_port 3002 }
 server s1 0.0.0.0:0 maxconn 1