mqtt-proxy
mqtt-proxy 插件是一个 L4 插件,支持将 MQTT 请求代理和负载均衡到 MQTT 服务器。它支持 MQTT 版本 3.1.x 和 5.0。该插件必须在流路由上配置,并且 APISIX 需要启用 L4 流量代理。
示例
默认情况下,APISIX 仅代理 L7 流量。在继续示例之前,请先启用 L4 流量代理。
- Host or Docker
- Kubernetes (Helm)
在网关配置文件中新增或更新以下配置:
apisix:
proxy_mode: http&stream # 同时启用 L4 和 L7 代理
stream_proxy: # 配置 L4 代理
tcp:
- 9100 # 设置 TCP 代理监听端口
重新加载网关以使更改生效。网关现在应开始在 9100 端口监听 L4 流量。
对于 Helm 部署,请更新用于渲染 stream proxy 监听器的 Chart values,并保留 values 文件中的其他配置。
对于 APISIX Helm Chart,设置以下 values:
service:
stream:
enabled: true
tcp:
- 9100
对于 API7 网关 Helm Chart,设置以下 values:
gateway:
stream:
enabled: true
tcp:
- addr: 9100
然后使用当前网关 release 对应的 Chart 应用 values 文件:
helm upgrade <release-name> <chart-name> -n <namespace> -f values.yaml
以下示例使用 Mosquitto 项目中的 MQTT 客户端来发布和订阅消息。你可以从此处下载它,或使用你选择的任何其他 MQTT 客户端。
代理到 MQTT 代理服务器
以下示例演示了如何配置流路由,将流量代理到托管的 MQTT 服务器,并验证 APISIX 能否成功代理 MQTT 消息。
创建一个指向 MQTT 服务器的流路由,并配置 mqtt-proxy 插件:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/stream_routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "mqtt-route",
"plugins": {
"mqtt-proxy": {
"protocol_name": "MQTT",
"protocol_level": 4
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"test.mosquitto.org:1883": 1
}
}
}'
services:
- name: mqtt-service
upstream:
name: default
scheme: tcp
nodes:
- host: test.mosquitto.org
port: 1883
weight: 1
stream_routes:
- name: mqtt-route
server_port: 9100
plugins:
mqtt-proxy:
protocol_name: MQTT
protocol_level: 4
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
Gateway API 目前不支持挂载 L4 插件,因此暂时无法使用 Gateway API 完成此示例。
使用 APISIX CRD 将 mqtt-proxy 插件挂载到流路由:
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: mqtt-broker
spec:
type: ExternalName
externalName: test.mosquitto.org
ports:
- name: mqtt
port: 1883
targetPort: 1883
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: mqtt-route
spec:
ingressClassName: apisix
stream:
- name: mqtt-route
protocol: TCP
match:
ingressPort: 9100
backend:
serviceName: mqtt-broker
servicePort: 1883
plugins:
- name: mqtt-proxy
enable: true
config:
protocol_name: MQTT
protocol_level: 4
应用配置:
kubectl apply -f mqtt-proxy-ic.yaml
打开两个终端会话。在第一个会话中,订阅测试主题:
mosquitto_sub -h test.mosquitto.org -p 1883 -t "test/apisix"
在另一个会话中,向创建的路由发布一条示例消息:
mosquitto_pub -h 127.0.0.1 -p 9100 -t "test/apisix" -m "Hello APISIX"
你应该会在第一个终端中看到消息 Hello APISIX。
负载均衡 MQTT 流量
以下示例演示了如何配置流路由,将 MQTT 流量负载均衡到不同的 MQTT 服务器。
启用插件后,它会注册一个变量 mqtt_client_id,可用于负载均衡。具有不同客户端 ID 的 MQTT 连接将根据一致性哈希算法被转发到不同的上游节点。如果缺 少客户端 ID,则将使用客户端 IP 代替。
创建一个指向两个 MQTT 服务器的流路由,并配置 mqtt-proxy 插件:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/stream_routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "mqtt-route",
"plugins": {
"mqtt-proxy": {
"protocol_name": "MQTT",
"protocol_level": 4
}
},
"upstream": {
"type": "chash",
"key": "mqtt_client_id",
"nodes": [
{
"host": "test.mosquitto.org",
"port": 1883,
"weight": 1
},
{
"host": "broker.mqtt.cool",
"port": 1883,
"weight": 1
}
]
}
}'
services:
- name: mqtt-service
upstream:
name: default
scheme: tcp
type: chash
key: mqtt_client_id
nodes:
- host: test.mosquitto.org
port: 1883
weight: 1
- host: broker.mqtt.cool
port: 1883
weight: 1
stream_routes:
- name: mqtt-route
server_port: 9100
plugins:
mqtt-proxy:
protocol_name: MQTT
protocol_level: 4
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
Gateway API 目前不支持挂载 L4 插件,因此暂时无法使用 Gateway API 完成此示例。
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: mqtt-brokers
spec:
ports:
- name: mqtt
port: 1883
protocol: TCP
---
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
namespace: aic
name: mqtt-brokers-1
labels:
kubernetes.io/service-name: mqtt-brokers
addressType: FQDN
ports:
- name: mqtt
protocol: TCP
port: 1883
endpoints:
- addresses:
- test.mosquitto.org
- addresses:
- broker.mqtt.cool
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: mqtt-brokers
spec:
ingressClassName: apisix
loadbalancer:
type: chash
key: mqtt_client_id
hashOn: vars
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: mqtt-route
spec:
ingressClassName: apisix
stream:
- name: mqtt-route
protocol: TCP
match:
ingressPort: 9100
backend:
serviceName: mqtt-brokers
servicePort: 1883
plugins:
- name: mqtt-proxy
enable: true
config:
protocol_name: MQTT
protocol_level: 4
应用配置:
kubectl apply -f mqtt-proxy-ic.yaml
对于 Admin API 和 ADC 示例,请打开三个终端会话。在第一个会话中,订阅第一个 MQTT 代理上的测试主题:
mosquitto_sub -h test.mosquitto.org -p 1883 -t "test/apisix"
在第二个终端中,订阅第二个 MQTT 代理上的相同主题:
mosquitto_sub -h broker.mqtt.cool -p 1883 -t "test/apisix"
在第三个终端中,多次运行以下命令向路由发送示例消息:
mosquitto_pub -h 127.0.0.1 -p 9100 -i publisher-1 -t "test/apisix" -m "Hello from publisher-1"
mosquitto_pub -h 127.0.0.1 -p 9100 -i publisher-2 -t "test/apisix" -m "Hello from publisher-2"
你应该会在订阅者终端中看到已发布的消息,从而验证可以将不同的 mqtt_client_id 值路由到不同的上游 Broker。