在 Envoy 1.28.0 上调试通过 websockets 传输的 MQTT
我已将我们的 Envoy 安装从 Envoy 1.11.1 迁移到 1.28.0,现在也使用 SNI 来选择正确的证书。
迁移的一个重要部分是将 Envoy 配置的语法从 v2 API 升级到 v3 API。
升级进行得很顺利,除了我们基于 WebSocket 的 MQTT 服务(基于 VerneMQ)不能按预期运行。
起初我以为问题出在 envoy 上。在尝试了许多超时选项并查阅了 envoy 文档后,我决定使用新的路由和背后的不同代理(Mosquitto)进行实验。
以下配置适用于作为代理的 Mosquitto,以防其他人遇到同样的问题。
下面是我的 envoy.yaml 摘录(完整配置超过 87000 行,由模板脚本生成,因为 SNI 和我上面提到的每个域必须有单独的侦听器):
静态资源:
listeners:
- address:
socket_address:
address:0.0.0.0
port_value:443
per_connection_buffer_limit_bytes:32768 # 32 KiB
listener_filters:
- name: tls_inspector
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector
filter_chains:
- filter_chain_match:
server_names: ["picockpit.com", "www.picockpit.com", "picockpit.com:443","www.picockpit.com:443"]
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificates:
- certificate_chain: { filename: "/certs/letsencrypt/live/picockpit.com/fullchain.pem" }
private_key: { filename: "/certs/letsencrypt/live/picockpit.com/privkey.pem" }
alpn_protocols:[ "h2,http/1.1" ]
filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type:自动
http_filters:
- name: envoy.filters.http.compressor
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.http.compressor.v3.Compressor
compressor_library:
name: text_optimized
typed_config:
'@type': type.googleapis.com/envoy.extensions.compression.gzip.compressor.v3.Gzip
压缩级别BEST_SPEED
compression_strategy:default_strategy
memory_level: 9
window_bits:15
chunk_size: 16384
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
common_http_protocol_options:
idle_timeout:3600s # 1 小时
use_remote_address: true
xff_num_trusted_hops:0
route_config:
virtual_hosts:
- 名称: 后台
域:["picockpit.com", "www.picockpit.com", "picockpit.com:443","www.picockpit.com:443"]
路由:
- match:{ path:"/pidoctor"}
重定向:
path_redirect: "/raspberry-pi/pidoctor-raspberry-pi-system-health-monitor/"
- match:{ prefix:"/pidoctor/"}
redirect:
path_redirect: "/raspberry-pi/pidoctor-raspberry-pi-system-health-monitor/" 重定向
- match:{ prefix:"/mqtt/test" }
route:
prefix_rewrite:"/mqtt"
集群: target_test
timeout:0s
空闲超时:0s
升级配置:
- upgrade_type:"websocket
enabled: true
- match:{ prefix:"/" }
路由:
cluster: target_main
timeout:0s
集群:
- 名称: target_test
connect_timeout:5s
per_connection_buffer_limit_bytes:32768 # 32 千字节
类型: STRICT_DNSSTRICT_DNS
lb_policy:ROUND_ROBIN
load_assignment:
集群名称: target_test
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: mosquitto-test.test-network
port_value: 8025
请注意,我省略了其他服务和路由的大部分配置,也没有提供 target_main 集群信息(因为它与通过 websockets 的 MQTT 情况无关)。
注意超时:0s 值,这对 MQTT 连接的继续很重要,而不是像默认值那样在 15 秒后超时。
我还强调了我认为与允许连接升级为 websockets(以便通过它们传输 MQTT)相关的其他部分。还请注意 端口号 作为额外的匹配域输入。
Mosquitto docker-compose.yml:
版本:'3.6
服务
mosquitto:
image: eclipse-mosquitto
container_name: mosquitto-test
hostname: mosquitto-test
networks:
- test_net
restart:"no
user:"root:root
卷:
- 类型:绑定
源: ./mosquitto.conf
目标: /mosquitto/config/mosquitto.conf/mosquitto/config/mosquitto.conf
网络
test_net:
external:
名称: test-network
mosquitto.conf:
监听器 8025
协议 websockets
allow_anonymous true
日志类型 all
用于验证连接的工具:
2023 年 11 月 13 日更新
MQTT 又上线了,还有 VerneMQ:
虽然我曾多次重启 VerneMQ,但显然没有等足够长的时间让它稳定下来。今天我的一位同事重新启动了 VerneMQ,它现在可以正常工作了。看来,它需要 10 - 15 分钟(在我们的设置中)才能完全响应并正常工作。
因此,我可以确认上述 envoy 配置也适用于 VerneMQ。
经验教训
如果有什么问题、 尝试用另一种工具复制交互过程中的问题 - 如果它能在那里工作,那么问题可能不在你更改的第一个工具上,而在它需要与之配合的第二个工具上。
和一些额外的好东西:
在线文档
- https://www.envoyproxy.io/docs
- https://www.envoyproxy.io/docs/envoy/v1.28.0/ (特别针对当前的特使版本)
- https://github.com/envoyproxy/envoy/blob/main/configs/envoyproxy_io_proxy_http3_downstream.yaml - HTTP3 配置示例
- https://codilime.com/blog/envoy-configuration/ - 理解特使
- https://pi3g.com/envoy-docker-and-websockets-debugging-and-configuration/ - 关于 websockets 和 envoy(PiCockpit 中使用 websockets 传输 MQTT)--之前的文章基于 envoy v1.11.1 版本
实用工具
- https://http3check.net/ - 允许检查是否支持 HTTP/3
- HiveMQ websocket 客户端