Here is my context:
I have a Lua script that registers an action on http_req, and make a HTTP call to a third party on each incoming request.
This works fine.
The issue is that the third-party host I’m reaching has multiple IPs defined in the DNS record, and I need to distribute the load of incoming requests to all those IP.
If I don’t, the load will is too large for one single LB of the third-party.
By default, as the DNS is resolved only once at startup, and the connections are kept open, my instance of haproxy sticks to one single IP, and overloads it, resulting in timeouts to get a response.
How can I properly load-balance between differents IP ?
I tried to use socket.dns.toip("third-party-host.com") to get a different IP to use, but this generates a certificate issue (using https) - that can not be disabled with the current httpclient implementation.
I’ve tried multiple things, but the basic problem is how to properly use multiple A records for the same FQDN in Lua Http client ?
I wouldn’t recommend using socket.* API because it is probably leveraging blocking functions which are not compatible with haproxy Lua’s event driven engine. When using external libraries, you should ensure that functions you rely on don’t wait for events and give the hand back to haproxy, see: https://www.arpalert.org/haproxy-lua.html#h204
By default, as the DNS is resolved only once at startup, and the connections are kept open, my instance of haproxy sticks to one single IP, and overloads it, resulting in timeouts to get a response.
However if multiple records are returned for the same DNS at a given time, haproxy will only consider the first returned entry. So you may force it to renew it’s cache by playing with the “timeout resolve” from resolvers section, but it may not suit your needs.
In this case, if you can’t deal with the builtin resolver’s behavior, and if you are able to query the records for a given DNS through an HTTP webservice at a defined address for example, you could leverage that webservice using the lua httpclient (or leverage core.tcp for a TCP service), and then iterate over raw IPs (from Lua) to make the actual httpclient request the server with the expected A record (and fallback to other IPs until one request succeeds for instance).
Another solution is to define another listener/proxy in haproxy and use DNS autodiscovery (with server-template), so that HAProxy discovers all IPs for a given DNS entry. You may then choose “roundrobin” load-balancing policy for that backend and leverage this “local” proxy directly from Lua’s httpclient (ie: forward requests to local listener which performs the discovery and load-balancing instead of requesting using the endpoint DNS from Lua directly). See: DNS for Service Discovery in HAProxy