【发布时间】:2023-03-19 11:48:01
【问题描述】:
我已经转了整整一天的时间来试图弄清楚这一点。我对 Traefik 还是比较陌生。目标是在云中建立一个安全的 MQTT 代理。问题是我可以使用任何使用mqtts://broker.mydomain.com:8883 的MQTT 客户端进行连接,但是当我需要通过wss://broker.mydomain.com:9001 使用websockets 时,我就没有运气了。
docker-compose.yml
version: "3.6"
networks:
traefik-global-proxy:
name: "traefik-global-proxy"
services:
traefik:
image: "traefik:v2.2"
container_name: "traefik"
networks:
- traefik-global-proxy
ports:
- "80:80"
- "443:443"
- "8883:8883"
- "9001:9001"
volumes:
# - "./traefik/traefik.toml:/etc/traefik/traefik.toml"
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./logs:/logs"
command:
- "--log.level=DEBUG"
- "--api=true"
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--accesslog=true"
- "--accesslog.filepath=/logs/access.log"
# Entrypoints
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.mqtt.address=:8883"
- "--entrypoints.websocket.address=:9001"
# Redirect http to https
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https" # Let's encrypt configuration
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.email=email@domain.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.broker.mydomain.com`)
&& (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.dashboard.middlewares=auth"
# echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g
- "traefik.http.middlewares.auth.basicauth.users=username:REDACTED"
mqtt:
image: "eclipse-mosquitto"
container_name: "mosquitto"
networks:
- traefik-global-proxy
restart: always
expose:
- "8883"
- "9001"
volumes:
- "./mosquitto/config:/mosquitto/config/"
- "./logs:/logs"
- "./data:/data"
labels:
- "traefik.enable=true"
- "traefik.http.routers.mqtt.rule=Host(`broker.mydomain.com`)"
- "traefik.http.routers.mqtt.entrypoints=websecure"
- "traefik.http.routers.mqtt.tls.certresolver=letsencrypt"
- "traefik.http.services.mqtt.loadbalancer.server.port=9001"
- "traefik.tcp.routers.mqtt.rule=HostSNI(`broker.mydomain.com`)"
- "traefik.tcp.routers.mqtt.entrypoints=mqtt"
- "traefik.tcp.routers.mqtt.tls.certresolver=letsencrypt"
- "traefik.tcp.services.mqtt.loadbalancer.server.port=8883"
mosquitto.conf
listener 8883 0.0.0.0
protocol mqtt
listener 9001 0.0.0.0
protocol websockets
allow_anonymous true
password_file /mosquitto/config/mosquitto.password
persistence true
persistence_file /data/mosquitto.db
log_dest file /logs/mosquitto.log
这是使用 vue create mqtt-vue 创建的独立 Vue 测试,但未成功:
App.vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js App" />
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
import mqtt from "mqtt";
export default {
name: "App",
components: {
HelloWorld,
},
data: () => ({
connection: {
host: "broker.mydomain.com",
port: 9001,
protocol: "wss",
username: "USERNAME",
password: "PASSWORD",
endpoint: "/",
clean: true, // Set to false to receive QoS 1 and 2 messages while offline
connectTimeout: 3 * 1000,
reconnectPeriod: 1 * 1000,
// clientId: `my-client-${uuidv4().substring(0, 8)}`,
keepalive: 30,
},
client: {
connected: false,
},
}),
mounted() {
console.log("MOUNTED");
const { host, port, endpoint, ...options } = this.connection;
const connectUrl = `wss://${host}:${port}${endpoint}`;
console.log(connectUrl, options);
this.client = mqtt.connect(connectUrl, options);
this.client.on("connect", this._onConnect);
this.client.on("error", (error) => {
console.warn("Connection failed", error);
});
},
methods: {
_onConnect() {
console.log("onConnect", this.client.connected);
},
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
任何帮助将不胜感激。我一定是在做一些愚蠢的事情。它只是不适合我。希望有人能指出这个问题,我和其他人可以在未来从这篇文章中学习。
【问题讨论】:
-
只是尝试一下,删除
endpoint或将其设置为/mqtt,因为这是 MQTT over WebSockets 的预期路径 -
我相信
traefik.http.routers.mqtt.entrypoints=websecure表示 traefik 将使用端口 443 进行 websocket 连接,但您正在尝试连接端口 9001;更改端口或使用traefik.http.routers.mqtt.entrypoints=websocket。 -
你是我的英雄!我不敢相信我没有看到。希望上面的完整示例以及您建议的解决方案对将来的人们有所帮助。