端口复用-使用haproxy代理端口的http协议、mqtt协议的流量
现在有一个新的需求,21883端口需要同时代理mqtt协议和http协议的流量,所以需要实现端口复用,我先后尝试了nginx和haproxy,nginx那边我没有成功,使用haproxy成功了,记录一下。
haproxy,我使用过2.4.22-f8e3218和3.0.5-8e879a5版本,都可以通过以下配置实现需求:
global log stdout local0 info maxconn 20000 daemon stats timeout 30s defaults log global # 继承global的debug日志级别和输出方式 mode tcp option tcplog option dontlognull # 不记录空请求,减少冗余 option logasap # 尽早输出日志,避免连接断开后日志丢失 option redispatch retries 3 timeout http-request 5s timeout queue 30s timeout connect 5s timeout client 30s timeout server 30s timeout tunnel 1h # 适配MQTT长连接 frontend main_frontend bind :21883 # 业务端口 mode tcp # 性能优化:300ms检测延迟,捕获首包 tcp-request inspect-delay 300ms # 强制等待首包有数据(payload长度>0)后再分流,不允许提前转发 tcp-request content accept if { req.len gt 0 } # 若超过300ms仍无首包,默认拒绝(避免空连接占用资源,可选) tcp-request content reject if { req.len eq 0 } # # | 消息类型 | 功能描述 | 高4位取值(二进制) | 首字节范围(十六进制) | 典型首字节示例 | # |------------------------|-------------------------------------------|---------------------|------------------------|----------------| # | CONNECT | 客户端连接到服务器 | 0001 | 10 ~ 1F | 10(标志位全0)| # | CONNACK | 服务器响应客户端连接请求 | 0010 | 20 ~ 2F | 20(标志位固定0)| # | PUBLISH | 客户端/服务器发送消息(最核心类型) | 0011 | 30 ~ 3F | 30(QoS 0)、31(QoS 1)| # | PUBACK | 响应 PUBLISH(QoS 1) | 0100 | 40 ~ 4F | 40(标志位固定0)| # | PUBREC | 响应 PUBLISH(QoS 2 第一步) | 0101 | 50 ~ 5F | 50(标志位固定0)| # | PUBREL | 响应 PUBREC(QoS 2 第二步) | 0110 | 60 ~ 6F | 62(标志位固定2)| # | PUBCOMP | 响应 PUBREL(QoS 2 第三步) | 0111 | 70 ~ 7F | 70(标志位固定0)| # | SUBSCRIBE | 客户端订阅主题 | 1000 | 80 ~ 8F | 82(标志位固定2)| # | SUBACK | 服务器响应订阅请求 | 1001 | 90 ~ 9F | 90(标志位固定0)| # | UNSUBSCRIBE | 客户端取消订阅 | 1010 | A0 ~ AF | A2(标志位固定2)| # | UNSUBACK | 服务器响应取消订阅 | 1011 | B0 ~ BF | B0(标志位固定0)| # | PINGREQ | 客户端发送心跳请求 | 1100 | C0 ~ CF | C0(标志位固定0)| # | PINGRESP | 服务器响应心跳请求 | 1101 | D0 ~ DF | D0(标志位固定0)| # | DISCONNECT | 客户端/服务器断开连接 | 1110 | E0 ~ EF | E0(标志位固定0)| # # 简化MQTT检测 acl is_mqtt_10 req.payload(0,1) -m bin 10 # 客户端连接到服务器 # acl is_mqtt_20 req.payload(0,1) -m bin 20 # 服务器响应客户端连接请求 acl is_mqtt_30 req.payload(0,1) -m bin 30 # 客户端/服务器发送消息 acl is_mqtt_31 req.payload(0,1) -m bin 31 # 客户端/服务器发送消息 acl is_mqtt_32 req.payload(0,1) -m bin 32 # 客户端/服务器发送消息 acl is_mqtt_82 req.payload(0,1) -m bin 82 # 客户端订阅主题 # acl is_mqtt_90 req.payload(0,1) -m bin 90 # 服务器响应订阅请求 acl is_mqtt_A2 req.payload(0,1) -m bin a2 # 客户端取消订阅 acl is_mqtt_B0 req.payload(0,1) -m bin b0 # 服务器响应取消订阅 acl is_mqtt_D0 req.payload(0,1) -m bin d0 # 服务器响应心跳请求 acl is_mqtt_E0 req.payload(0,1) -m bin e0 # 客户端/服务器断开连接 # 分流规则:MQTT优先,默认走HTTP # use_backend mqtt_servers if is_mqtt_10 or is_mqtt_20 or is_mqtt_30 or is_mqtt_31 or is_mqtt_32 or is_mqtt_82 or is_mqtt_90 or is_mqtt_A2 or is_mqtt_B0 or is_mqtt_D0 or is_mqtt_E0 use_backend mqtt_servers if is_mqtt_10 or is_mqtt_30 or is_mqtt_31 or is_mqtt_32 or is_mqtt_82 or is_mqtt_A2 or is_mqtt_B0 or is_mqtt_D0 or is_mqtt_E0 default_backend http_servers backend http_servers mode http balance roundrobin option httpchk # HTTP健康检查 http-check send meth OPTIONS uri / ver HTTP/1.1 hdr Host localhost # server http_server1 192.168.50.22:10008 check maxconn 1000 # 后端健康检查 server http_server1 192.168.50.22:10008 backend mqtt_servers mode tcp balance source # 源IP哈希,MQTT重连不换后端 # server mqtt_server1 xx.xx.x.xx:1883 check maxconn 5000 # MQTT后端 server mqtt_server1 xx.xx.xx.xx:1883
2.4.22版本是在主机上部署的,所以关于日志的部分应该要更改下。
3.0.5版本我是容器化部署的,日志的那部分可以不用改;
部分日志输出:
[NOTICE] (1) : haproxy version is 3.0.5-8e879a5 [NOTICE] (1) : path to executable is /usr/local/sbin/haproxy [WARNING] (1) : Exiting Master process... [WARNING] (8) : Proxy main_frontend stopped (cumulated conns: FE: 25, BE: 0). [WARNING] (8) : Proxy http_servers stopped (cumulated conns: FE: 0, BE: 27). [WARNING] (8) : Proxy mqtt_servers stopped (cumulated conns: FE: 0, BE: 1). <132>Sep 10 05:18:15 haproxy[8]: Proxy main_frontend stopped (cumulated conns: FE: 25, BE: 0). <132>Sep 10 05:18:15 haproxy[8]: Proxy http_servers stopped (cumulated conns: FE: 0, BE: 27). <132>Sep 10 05:18:15 haproxy[8]: Proxy mqtt_servers stopped (cumulated conns: FE: 0, BE: 1). [WARNING] (1) : Current worker (8) exited with code 0 (Exit) [WARNING] (1) : All workers exited. Exiting... (0) [NOTICE] (1) : New worker (9) forked [NOTICE] (1) : Loading success. <134>Sep 10 05:18:31 haproxy[9]: 192.168.50.25:2674 [10/Sep/2025:05:18:31.939] main_frontend mqtt_servers/mqtt_server1 8/6/+13 +0 -- 1/1/1/1/0 0/0 <134>Sep 10 06:09:58 haproxy[9]: 192.168.50.25:3817 [10/Sep/2025:06:09:58.609] main_frontend mqtt_servers/mqtt_server1 7/6/+12 +0 -- 1/1/1/1/0 0/0 <134>Sep 10 06:10:10 haproxy[9]: 192.168.50.194:46212 [10/Sep/2025:06:10:10.570] main_frontend http_servers/http_server1 0/0/+1 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:11 haproxy[9]: 192.168.50.194:46226 [10/Sep/2025:06:10:11.588] main_frontend http_servers/http_server1 0/0/+2 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:12 haproxy[9]: 192.168.50.194:46230 [10/Sep/2025:06:10:12.607] main_frontend http_servers/http_server1 0/0/+1 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:13 haproxy[9]: 192.168.50.194:46232 [10/Sep/2025:06:10:13.626] main_frontend http_servers/http_server1 0/0/+1 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:14 haproxy[9]: 192.168.50.194:46242 [10/Sep/2025:06:10:14.645] main_frontend http_servers/http_server1 0/0/+0 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:15 haproxy[9]: 192.168.50.194:46250 [10/Sep/2025:06:10:15.659] main_frontend http_servers/http_server1 0/0/+1 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:16 haproxy[9]: 192.168.50.194:46256 [10/Sep/2025:06:10:16.677] main_frontend http_servers/http_server1 0/0/+0 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:17 haproxy[9]: 192.168.50.194:46260 [10/Sep/2025:06:10:17.690] main_frontend http_servers/http_server1 0/0/+0 +202 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:18 haproxy[9]: 192.168.50.194:46272 [10/Sep/2025:06:10:18.705] main_frontend http_servers/http_server1 0/0/+1 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:19 haproxy[9]: 192.168.50.194:46280 [10/Sep/2025:06:10:19.726] main_frontend http_servers/http_server1 0/0/+1 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:20 haproxy[9]: 192.168.50.194:36492 [10/Sep/2025:06:10:20.745] main_frontend http_servers/http_server1 0/0/+0 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:21 haproxy[9]: 192.168.50.194:36502 [10/Sep/2025:06:10:21.756] main_frontend http_servers/http_server1 0/0/+1 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:22 haproxy[9]: 192.168.50.194:36514 [10/Sep/2025:06:10:22.769] main_frontend http_servers/http_server1 0/0/+1 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:23 haproxy[9]: 192.168.50.194:36528 [10/Sep/2025:06:10:23.787] main_frontend http_servers/http_server1 0/0/+1 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:24 haproxy[9]: 192.168.50.194:36542 [10/Sep/2025:06:10:24.807] main_frontend http_servers/http_server1 0/0/+1 +202 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:25 haproxy[9]: 192.168.50.194:36556 [10/Sep/2025:06:10:25.826] main_frontend http_servers/http_server1 0/0/+0 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:26 haproxy[9]: 192.168.50.194:36568 [10/Sep/2025:06:10:26.838] main_frontend http_servers/http_server1 0/0/+0 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:10:27 haproxy[9]: 192.168.50.194:36578 [10/Sep/2025:06:10:27.850] main_frontend http_servers/http_server1 0/0/+1 +2349 -- 2/2/1/1/0 0/0 <134>Sep 10 06:25:37 haproxy[9]: 192.168.50.25:10005 [10/Sep/2025:06:25:37.169] main_frontend mqtt_servers/mqtt_server1 8/6/+13 +0 -- 1/1/1/1/0 0/0
浙公网安备 33010602011771号