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.