I’m running the latest haproxytech/haproxy-ubuntu Docker image:
HAProxy version 2.5.1-86b093a 2022/01/11 - https://haproxy.org/
Running on: Linux 5.4.0-91-generic #102-Ubuntu SMP Fri Nov 5 16:31:28 UTC 2021 x86_64
My goal is to split MQTT connections between 3 backend servers while giving the clients a possibility to stick to one of them by using MQTT username as an ID. So far I managed to understand the concepts (except maybe sharing server template between two backends, but that’s not the issue now) and come up with the following config:
global
log stdout format raw daemon debug
stats socket :9999 level admin expose-fd listeners
defaults
log global
mode tcp
option tcplog
maxconn 1024000
timeout connect 30000
timeout client 600s
timeout server 600s
frontend mqtt_tcp
mode tcp
option tcplog
bind *:1883
bind *:8883 ssl crt /etc/haproxy-ssl/my.domain.com.pem
default_backend mqtt_tcp_back
frontend mqtt_ws
mode tcp
option tcplog
bind *:8083 ssl crt /etc/haproxy-ssl/my.domain.com.pem
default_backend mqtt_ws_back
resolvers cluster_dns
nameserver dns1 10.96.0.10:53
accepted_payload_size 8192 # allow larger DNS payloads
backend mqtt_usernames
stick-table type string len 32 size 100k expire 30m
backend mqtt_tcp_back
mode tcp
stick on req.payload(0,0),mqtt_field_value(connect,username) table mqtt_usernames
server-template mqtt_tcp 10 mqtt-daemon-pods.default.svc.cluster.local:1883 check resolvers cluster_dns init-addr none
backend mqtt_ws_back
mode tcp
stick on req.payload(0,0),mqtt_field_value(connect,username) table mqtt_usernames
server-template mqtt_tcp 10 mqtt-daemon-pods.default.svc.cluster.local:9001 check resolvers cluster_dns init-addr none
Everything is more or less fine. I can see the table being populated with correct keys
# table: mqtt_usernames, type: string, size:102400, used:1
0x56047667ac50: key=gateway use=0 exp=1518633 server_id=1 server_key=mqtt_tcp1
But not all the connections stick to the mqtt_tcp1. When I run
mosquitto_sub -h 192.168.0.80 -u gateway -P qwerty -t test
for run in {1..50}; do mosquitto_pub -h 192.168.0.80 -u gateway -P qwerty -t test -m "hello $run"; done
I see 3-5 messages missing, like:
...
hello 42
hello 43
hello 45
hello 47
hello 48
hello 49
hello 50
and the log
10.244.0.1:47865 [04/Feb/2022:10:50:04.908] mqtt_tcp mqtt_tcp_back/mqtt_tcp1 1/0/0 4 -- 2/2/1/1/0 0/0
10.244.0.1:64431 [04/Feb/2022:10:50:04.910] mqtt_tcp mqtt_tcp_back/mqtt_tcp1 1/0/0 4 -- 2/2/1/1/0 0/0
10.244.0.1:7948 [04/Feb/2022:10:50:04.914] mqtt_tcp mqtt_tcp_back/mqtt_tcp2 1/0/0 4 -- 2/2/1/0/0 0/0
10.244.0.1:27261 [04/Feb/2022:10:50:04.916] mqtt_tcp mqtt_tcp_back/mqtt_tcp1 1/0/0 4 -- 2/2/1/1/0 0/0
10.244.0.1:41658 [04/Feb/2022:10:50:04.919] mqtt_tcp mqtt_tcp_back/mqtt_tcp3 1/0/0 4 -- 2/2/1/0/0 0/0
10.244.0.1:38141 [04/Feb/2022:10:50:04.921] mqtt_tcp mqtt_tcp_back/mqtt_tcp1 1/0/0 4 -- 2/2/1/1/0 0/0
10.244.0.1:62642 [04/Feb/2022:10:50:04.924] mqtt_tcp mqtt_tcp_back/mqtt_tcp1 1/0/0 4 -- 2/2/1/1/0 0/0
10.244.0.1:23143 [04/Feb/2022:10:50:04.926] mqtt_tcp mqtt_tcp_back/mqtt_tcp1 1/0/0 4 -- 2/2/1/1/0 0/0
10.244.0.1:3238 [04/Feb/2022:10:50:04.929] mqtt_tcp mqtt_tcp_back/mqtt_tcp1 1/0/0 4 -- 2/2/1/1/0 0/0
Am I missing something simple? Can some logging be added to see why the respective servers are chosen? I already tried removing the WS backend and TLS termination, to leave only port 1883. It did not help. The closest problem I’ve seen so far is this but with not too much enthusiasm about it.