EMQX 高效可水平擴展的 WebSocket + MQTT 服務

今天介紹 EMQX 這個高校可水平擴展的 Message Queue,同時支援 MQTT 與 WebSocket 可以讓不同裝置快速整合溝通。在 IoT 物聯網、智慧工業、雲端服務、即時通知、設備監控、前後端事件串流等場景裡,如何建立一個 穩定、可擴展、低延遲 的訊息傳輸系統,往往是系統設計的核心問題。如果你需要的不只是單純的 WebSocket Server,而是一套可以同時支援 MQTT 協議、WebSocket 接入、水平擴展、JWT 驗證授權、持久化能力、高負載吞吐 的訊息平台,那麼 EMQX 會是一個很值得評估的選項。EMQX 作為一款採用 Apache 2.0 開源協議的高效能 MQTT Broker,支援千萬等級的 IoT 設備連接,本文將帶你從零開始架設並整合 MySQL 認證,同時透過 Caddy 實現 WSS 安全連線。

這篇文章會從基本概念開始,帶你快速理解:

  • EMQX 是什麼
  • WebSocket 與 MQTT 的差異與關係
  • EMQX 的基本架構
  • 如何透過 Docker 快速架設
  • 如何整合 MySQL 做驗證或資料管理
  • 如何用 Linux CLI 與 MQTT.js 進行最小化驗證
  • 最後再搭配 Caddy 建立 wss:// 安全連線

如果你想要做的是一套能上 Production、又保有良好擴展性的即時訊息基礎設施,這會是一個不錯的起點。

為什麼是 EMQX?

EMQX 是一套高效能的 MQTT Broker,特別適合用在以下情境:

  • IoT 裝置資料上傳
  • 行動 App / Web 前端即時推播
  • 事件流轉與狀態同步
  • 需要高連線數與高併發訊息處理的系統
  • Queue 事件緩存

它的幾個核心特點很實用:

  • 原生支援 MQTT
  • 支援標準 WebSocket / Secure WebSocket
  • 可做叢集與水平擴展
  • 有完整 Dashboard 可管理
  • 可整合資料庫做身份驗證與 ACL
  • Docker 化部署容易

換句話說,EMQX 並不只是「一台 Broker」,而比較像是 一個可運營的訊息平台,可以大幅降低應用系統開發上線的時間。

WebSocket 與 MQTT 是什麼?兩者有什麼關係?

很多人在第一次接觸 EMQX 時,最容易混淆的就是:

WebSocket 跟 MQTT 到底是同一件事嗎?

答案是:不是。

WebSocket:一種雙向連線通道

WebSocket 是一個通訊協議,讓瀏覽器與伺服器之間可以建立 長連線、雙向傳輸 的通道。它很適合做:

  • 即時聊天
  • 即時通知
  • 前端 Dashboard 狀態更新
  • 遊戲或互動型應用

它解決的是「連線層」的底層問題,主要使用於瀏覽器端的連線技術。

MQTT:一種輕量級訊息協議

MQTT(Message Queuing Telemetry Transport)是一種輕量級的發布/訂閱訊息傳輸協定,專為低頻寬、高延遲或不穩定的網路環境設計。其核心角色包括:

  • Publisher(發布者):發送訊息到特定主題
  • Subscriber(訂閱者):訂閱感興趣的主題接收訊息
  • Broker(代理伺服器):負責接收發布訊息並轉發給相應的訂閱者

MQTT 發布 / 訂閱(Pub/Sub) 模型的訊息協議,常見於 IoT 領域。它的特點是:

  • 封包小
  • 傳輸效率高
  • 很適合不穩定網路
  • 支援 topic-based routing
  • 支援 QoS 等級

它解決的是「訊息格式與交換模型」的問題。MQTT 還提供了三種 QoS(Service Quality)層級:

  • QoS 0:最多傳送一次,適用於及時性要求高、可容忍遺漏的場景
  • QoS 1:至少傳送一次,確保訊息必定送達
  • QoS 2:精確傳送一次,適用於重要資料如支付確認

這樣的設計可以滿足大多數的訊息交換還環境。

兩者怎麼一起工作?

EMQX 可以讓 MQTT 不只跑在 TCP 上,也可以跑在 WebSocket 上。也就是說:

  • 裝置端可能用 MQTT/TCP 連進來
  • Web 前端則可以透過 MQTT over WebSocket
  • 最後都由 EMQX 作為訊息中樞統一處理

這也是 EMQX 很實用的地方:同一套訊息系統,可以同時服務設備與 Web 應用。

EMQX 架構概念介紹

 

可以先用下圖理解整體概念:

EMQX 架構圖

EMQX Dashboard 基本操作

EMQX 提供 Web Dashboard,對初期驗證與日常管理很方便。

通常預設入口會是:

  • http://localhost:18083

登入後,常見會用到的功能有:

查看連線 Clients

你可以看到目前有哪些客戶端連進來,包括:

  • Client ID
  • Username
  • 來源 IP
  • 連線時間
  • 協議類型(MQTT / WS)

這對排查連線問題很好用。

查看 Topics 與 Subscription

可以觀察:

  • 哪些 topic 正在被訂閱
  • 哪些 client 正在收哪些訊息

如果你在測試 pub/sub 流程,這一頁非常直觀。

規則引擎與整合

EMQX 也支援 rule engine、webhook、資料橋接等能力。
如果後續要把訊息導到資料庫、Kafka 或其他系統,這一塊會很重要。

Authentication / Authorization

在正式環境裡,最重要的不是「能連」,而是「誰可以連、能做什麼」。

你會需要設定:

  • 驗證(Authentication)
  • 授權(Authorization / ACL)

而這也是本文後面要搭配 MySQL 的原因。

用 Docker 快速架設 EMQX

先從最小可行版本開始,我們先透過設計 docker compose 建立 EMQX 服務,在 Linux Ubuntu 安裝 Docker Compose 教學可以參考「安裝最新穩定版的 Docker 與 Docker Compose 教學」這一篇文章。

前置需求

  • Docker Engine 20.10+
  • Docker Compose 2.0+

Docker EMQX 建制教學

docker-compose.yaml

version: "3.9"

services:
  emqx:
    image: emqx/emqx:5.7.0
    container_name: emqx
    restart: unless-stopped
    ports:
      - "1883:1883"     # MQTT TCP
      - "8083:8083"     # MQTT over WebSocket
      - "8883:8883"     # MQTT SSL
      - "18083:18083"   # Dashboard
    environment:
      EMQX_DASHBOARD__DEFAULT_USERNAME: admin
      EMQX_DASHBOARD__DEFAULT_PASSWORD: public
    volumes:
      - emqx_data:/opt/emqx/data
      - emqx_log:/opt/emqx/log

volumes:
  emqx_data:
  emqx_log:

建立好以後透過以下命令啟動:

docker-compose up -d

啟動完成開啟瀏覽器,輸入:http://localhost:18083 使用預設的帳號密碼 admin/public 登入以後可以看到 Dashboard 畫面如下:

emax-dashboard

EMQX 架設時常見 Port 說明如下:

  • 1883:標準 MQTT TCP
  • 8883:MQTT over SSL/TLS
  • 8083:MQTT over WebSocket
  • 8084:MQTT over WebSocket Secure(若直接由 EMQX 提供)
  • 18083:Dashboard 管理介面

如果你打算用 Caddy 統一收 TLS,通常會讓外部流量先進 Caddy,再轉發到 EMQX 的 8083,我們等下會完成這部份的整合。

Linux CLI 驗證 MQTT 連線 (mosquitto command)

如果你要在 Linux 上快速驗證 MQTT Broker,最方便的是使用 mosquitto-clients。Ubuntu Linux 安裝方式如下:

sudo apt update
sudo apt install -y mosquitto-clients

安裝完成以後,啟動一個 Terminal 進行訂閱

# 訂閱主題(無認證)

mosquitto_sub -h localhost -p 1883 -t "sensor/+/temperature"

啟動另一個 Terminal 發送訊息

# 發布訊息(無認證)

mosquitto_pub -h localhost -p 1883 -t "sensor/01/temperature" -m "Hello EMQX"

收到訊息如下:

mosquitto-testing

透過 WebSocket 測試連線

安裝 websocat CLI 測試工具,Ubuntu / Debian 安裝方式如下:

wget https://github.com/vi/websocat/releases/download/v1.14.0/websocat.x86_64-unknown-linux-musl

chmod +x websocat.x86_64-unknown-linux-musl

sudo mv websocat.x86_64-unknown-linux-musl /usr/local/bin/websocat

安裝完成以後我們透過 websocat 命令進行測試,如下:

啟動一個 Terminal 進行訂閱

# 訂閱主題(無認證)

websocat "ws://localhost:8083/mqtt" -L "mqtt-sub:testtopic/#"

啟動另一個 Terminal 發送訊息

# 發布訊息
websocat "ws://localhost:8083/mqtt" -L "mqtt-pub:testtopic/01:my_payload"

透過 Docker 整合 MySQL

如果你希望把帳號驗證、ACL 控制,甚至部分 metadata 放到資料庫管理,可以把 MySQL 一起編排進來。

docker compose file 修改如下:

version: "3.9"

services:
  emqx:
    image: emqx/emqx:5.7.0
    container_name: emqx
    restart: unless-stopped
    depends_on:
      - mysql
    ports:
      - "1883:1883"
      - "8083:8083"
      - "18083:18083"
    environment:
      EMQX_DASHBOARD__DEFAULT_USERNAME: admin
      EMQX_DASHBOARD__DEFAULT_PASSWORD: public
    volumes:
      - emqx_data:/opt/emqx/data
      - emqx_log:/opt/emqx/log

  mysql:
    image: mysql:8.0
    container_name: emqx_mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: emqx
      MYSQL_USER: emqx
      MYSQL_PASSWORD: emqxpass
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  emqx_data:
  emqx_log:
  mysql_data:

完成以後一樣透過以下命令更新啟動

docker compose up -d