10-1. 即時通訊協定概覽
認識 MQTT、XMPP、STOMP、AMQP 等協定的特性與應用場景
目錄
📨 即時通訊協定概覽
🎯 什麼是即時通訊協定?
想像一個郵局系統,有不同的郵寄方式:
- 平信:HTTP,寄出去就不管了,沒有回執
- 掛號信:有送達確認,但比較慢
- 快遞:專人配送,可以即時追蹤
- 郵政信箱:訂閱制,有新信就通知
即時通訊協定就像這些不同的郵寄方式,針對不同需求設計出不同的訊息傳遞機制。
🏗️ 常見的即時通訊協定
1️⃣ MQTT (Message Queuing Telemetry Transport)
特性:輕量級、低頻寬、低功耗
💡 比喻:訂閱制報紙
你訂閱了「體育版」,報社有新的體育新聞就會自動送到你家
不需要你每天去報社問「有新聞嗎?」適用場景:
- ⚡ IoT 物聯網裝置(智慧家居、感測器)
- 📱 行動裝置(省電、省流量)
- 🌐 網路不穩定環境
架構:發布/訂閱模式(Pub/Sub)
Publisher → Broker → Subscriber
裝置 A 發布 "temperature/living-room" = 25°C
裝置 B 訂閱 "temperature/#" → 收到通知Python 範例:
import paho.mqtt.client as mqtt
# 訂閱者
def on_connect(client, userdata, flags, rc):
print("連接成功")
client.subscribe("home/temperature") # 訂閱溫度主題
def on_message(client, userdata, msg):
print(f"收到訊息:{msg.topic} = {msg.payload.decode()}")
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("mqtt.example.com", 1883, 60)
client.loop_forever()# 發布者
import paho.mqtt.client as mqtt
client = mqtt.Client()
client.connect("mqtt.example.com", 1883, 60)
# 發布溫度資訊
client.publish("home/temperature", "25.5")
client.disconnect()2️⃣ XMPP (Extensible Messaging and Presence Protocol)
特性:開放、可擴展、即時
💡 比喻:即時通訊 App(LINE、WhatsApp)
可以傳文字、圖片、知道對方是否在線
還能建立群組、視訊通話適用場景:
- 💬 即時聊天應用
- 👥 社交平台
- 🎮 線上遊戲(顯示玩家在線狀態)
特點:
- ✅ 分散式架構(不依賴單一伺服器)
- ✅ 支援線上狀態(Presence)
- ✅ 端對端加密
- ✅ XML 格式(可讀性高但較占頻寬)
訊息格式:
<message to="user@example.com" from="alice@example.com" type="chat">
<body>Hello, how are you?</body>
</message>Python 範例:
import slixmpp
class MyBot(slixmpp.ClientXMPP):
def __init__(self, jid, password):
super().__init__(jid, password)
# 註冊事件處理器
self.add_event_handler("session_start", self.start)
self.add_event_handler("message", self.message)
async def start(self, event):
self.send_presence() # 發送線上狀態
await self.get_roster() # 獲取聯絡人列表
async def message(self, msg):
if msg['type'] in ('chat', 'normal'):
print(f"收到訊息:{msg['body']}")
msg.reply(f"你說:{msg['body']}").send()
# 使用
bot = MyBot('user@example.com', 'password')
bot.connect()
bot.process(forever=True)3️⃣ STOMP (Simple Text Oriented Messaging Protocol)
特性:簡單、文字導向、易於實作
💡 比喻:簡化版的郵局系統
規則簡單明瞭,任何人都能快速上手
不像 AMQP 那麼複雜專業適用場景:
- 🌐 Web 應用程式
- 🔄 訊息佇列
- 📊 即時數據推送
訊息格式:
SEND
destination:/queue/test
content-type:text/plain
Hello, STOMP!^@JavaScript + Node.js 範例:
// 前端(瀏覽器)
const client = new StompJs.Client({
brokerURL: 'ws://localhost:15674/ws',
onConnect: () => {
console.log('連接成功');
// 訂閱訊息
client.subscribe('/topic/notifications', (message) => {
console.log('收到通知:', message.body);
});
// 發送訊息
client.publish({
destination: '/topic/notifications',
body: 'Hello from client!'
});
}
});
client.activate();// 後端(Node.js + RabbitMQ)
const amqp = require('amqplib');
async function setupStomp() {
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
// 宣告交換機
await channel.assertExchange('notifications', 'topic', { durable: false });
// 訂閱訊息
const q = await channel.assertQueue('', { exclusive: true });
await channel.bindQueue(q.queue, 'notifications', '#');
channel.consume(q.queue, (msg) => {
console.log('收到訊息:', msg.content.toString());
}, { noAck: true });
}
setupStomp();4️⃣ AMQP (Advanced Message Queuing Protocol)
特性:企業級、可靠、功能完整
💡 比喻:專業物流公司(順豐、DHL)
提供各種配送選項:標準、快速、保價
保證不會遺失、可以追蹤、支援退件適用場景:
- 🏢 企業級應用
- 💼 金融交易系統
- 📦 訂單處理系統
- 🔄 微服務架構
核心概念:
Producer → Exchange → Queue → Consumer
Exchange 類型:
1. Direct:精確匹配 routing key
2. Topic:萬用字元匹配(*.error、log.#)
3. Fanout:廣播給所有佇列
4. Headers:根據 headers 屬性路由Python 範例(使用 RabbitMQ):
import pika
# 生產者
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
# 宣告交換機和佇列
channel.exchange_declare(exchange='logs', exchange_type='fanout')
channel.queue_declare(queue='task_queue', durable=True)
channel.queue_bind(exchange='logs', queue='task_queue')
# 發送訊息(持久化)
channel.basic_publish(
exchange='logs',
routing_key='',
body='Important task',
properties=pika.BasicProperties(
delivery_mode=2, # 訊息持久化
)
)
print("訊息已發送")
connection.close()# 消費者
def callback(ch, method, properties, body):
print(f"收到任務:{body.decode()}")
# 處理任務...
ch.basic_ack(delivery_tag=method.delivery_tag) # 確認處理完成
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='task_queue', durable=True)
# 設定 QoS:一次只處理一個訊息
channel.basic_qos(prefetch_count=1)
channel.basic_consume(
queue='task_queue',
on_message_callback=callback,
auto_ack=False # 手動確認
)
print('等待訊息...')
channel.start_consuming()📊 協定比較表
| 協定 | 傳輸模式 | 訊息格式 | 複雜度 | QoS | 適用場景 |
|---|---|---|---|---|---|
| MQTT | Pub/Sub | 二進位 | 簡單 | ✅ 3種 | IoT、行動裝置 |
| XMPP | 點對點/群組 | XML | 中等 | ✅ | 即時聊天、社交 |
| STOMP | Pub/Sub/Queue | 文字 | 簡單 | ❌ | Web 應用 |
| AMQP | Queue/Pub/Sub | 二進位 | 複雜 | ✅ | 企業級應用 |
🔍 如何選擇協定?
使用 MQTT 當你需要:
- ⚡ IoT 裝置通訊(智慧家居、感測器)
- 📱 行動裝置(省電、省流量)
- 🌐 網路不穩定環境
- 🔔 訂閱制推送通知
使用 XMPP 當你需要:
- 💬 即時聊天功能
- 👤 線上狀態顯示(在線/離線/忙碌)
- 🔐 端對端加密
- 🌍 分散式架構(不依賴單一伺服器)
使用 STOMP 當你需要:
- 🌐 Web 應用即時通訊
- 🚀 快速開發原型
- 📝 簡單易懂的協定
- 🔧 與 WebSocket 整合
使用 AMQP 當你需要:
- 🏢 企業級可靠性
- 💰 金融交易系統
- 📦 複雜路由需求
- 🔄 微服務通訊
- ✅ 訊息持久化和確認機制
🎓 實際應用案例
案例 1:智慧家居系統(MQTT)
# 溫度感測器發布數據
client.publish("home/living-room/temperature", "25.5")
client.publish("home/bedroom/temperature", "23.0")
# 空調訂閱溫度,自動調節
client.subscribe("home/+/temperature") # + 萬用字元匹配任何房間案例 2:即時聊天 App(XMPP)
# 發送訊息 + 顯示對方狀態
await bot.send_message(
mto="friend@example.com",
mbody="Hey, are you free?",
mtype="chat"
)
# 設定自己的狀態
bot.send_presence(pshow="away", pstatus="In a meeting")案例 3:電商訂單系統(AMQP)
# 訂單服務發送新訂單
channel.basic_publish(
exchange='orders',
routing_key='order.created',
body=json.dumps({
'order_id': '12345',
'user_id': 'user_001',
'total': 1500
})
)
# 庫存服務訂閱並處理
channel.queue_bind(exchange='orders', queue='inventory', routing_key='order.*')
# 通知服務發送 Email
channel.queue_bind(exchange='orders', queue='notifications', routing_key='order.*')🔐 安全性考量
1. 傳輸加密
# MQTT over TLS
client = mqtt.Client()
client.tls_set(ca_certs="ca.crt", certfile="client.crt", keyfile="client.key")
client.connect("mqtt.example.com", 8883)
# AMQP over SSL
connection = pika.BlockingConnection(
pika.ConnectionParameters(
host='localhost',
port=5671,
ssl_options=pika.SSLOptions(context)
)
)2. 身份驗證
# MQTT 使用者名稱/密碼
client.username_pw_set("username", "password")
# AMQP 身份驗證
credentials = pika.PlainCredentials('user', 'pass')
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost', credentials=credentials)
)3. 訊息完整性
# AMQP 訊息簽章
import hmac
import hashlib
def sign_message(message, secret_key):
signature = hmac.new(
secret_key.encode(),
message.encode(),
hashlib.sha256
).hexdigest()
return {'message': message, 'signature': signature}
# 發送簽章訊息
signed = sign_message('Important data', 'secret')
channel.basic_publish(exchange='', routing_key='queue', body=json.dumps(signed))🎯 常見面試題
Q1:MQTT 的 QoS 等級有哪些?
答案:
MQTT 提供 3 種 QoS(Quality of Service)等級:
QoS 0(At most once):最多一次
- 發送即忘,不確認
- 類似 UDP
- 最快但可能遺失
QoS 1(At least once):至少一次
- 確保送達,但可能重複
- 需要 PUBACK 確認
QoS 2(Exactly once):恰好一次
- 保證送達且不重複
- 四次握手(PUBREC → PUBREL → PUBCOMP)
- 最可靠但最慢
口訣:「零忘一重二恰好」(0=遺忘、1=重複、2=恰好)
# 使用不同 QoS
client.publish("topic", "message", qos=0) # 最快
client.publish("topic", "message", qos=1) # 平衡
client.publish("topic", "message", qos=2) # 最可靠Q2:AMQP 和 MQTT 的主要差異?
答案:
| 特性 | AMQP | MQTT |
|---|---|---|
| 設計目標 | 企業級訊息佇列 | IoT 輕量通訊 |
| 複雜度 | 高(支援多種交換機類型) | 低(簡單 Pub/Sub) |
| 訊息路由 | 複雜(Direct/Topic/Fanout/Headers) | 簡單(Topic 層級) |
| 訊息保證 | 持久化、事務、確認 | QoS 0/1/2 |
| 頻寬需求 | 較高 | 極低(2 bytes header) |
| 適用場景 | 金融、訂單處理 | 感測器、行動裝置 |
記憶技巧:
- AMQP = Advanced(進階企業用)
- MQTT = Minimal(最小物聯網用)
Q3:什麼是 Pub/Sub 模式?與點對點模式有何不同?
答案:
Pub/Sub(發布/訂閱):
一對多,發布者不知道誰會收到
報社(Publisher)→ 報紙(Topic)→ 訂閱者們(Subscribers)
- 報社發布新聞,不知道誰訂閱
- 訂閱者可以隨時加入/退出
- 一則新聞可以被多人看到Point-to-Point(點對點):
一對一,訊息只能被一個消費者處理
寄信人 → 信箱(Queue)→ 收信人
- 每封信只有一個收件人
- 信被取走後就沒了
- 適合任務分配程式碼比較:
# Pub/Sub(MQTT)
client.publish("news/sports", "Team A wins!") # 所有訂閱者都收到
# Point-to-Point(AMQP Queue)
channel.basic_publish(exchange='', routing_key='tasks', body='Task 1')
# 只有一個 worker 會處理Q4:如何保證訊息不遺失?
答案:
多層保護機制:
- 傳輸層保證(QoS):
# MQTT QoS 2:保證送達且不重複
client.publish("critical/data", payload, qos=2)- 持久化(Persistence):
# AMQP 訊息持久化
channel.basic_publish(
exchange='',
routing_key='task_queue',
body='Important task',
properties=pika.BasicProperties(
delivery_mode=2, # 持久化到硬碟
)
)
# 佇列持久化
channel.queue_declare(queue='task_queue', durable=True)- 手動確認(Manual ACK):
def callback(ch, method, properties, body):
print(f"處理:{body}")
# 處理完成後才確認
ch.basic_ack(delivery_tag=method.delivery_tag)
channel.basic_consume(
queue='task_queue',
on_message_callback=callback,
auto_ack=False # 手動確認
)- 重試機制:
# 死信佇列(Dead Letter Queue)
channel.queue_declare(
queue='main_queue',
arguments={
'x-dead-letter-exchange': 'dlx',
'x-message-ttl': 60000, # 60秒後進入死信
}
)口訣:「傳持認重」(傳輸保證、持久化、確認機制、重試)
Q5:XMPP 的 Presence 有什麼用途?
答案:
Presence(線上狀態) 讓使用者知道對方是否在線,就像 LINE 的「在線中」功能。
狀態類型:
<!-- 在線 -->
<presence/>
<!-- 離開 -->
<presence>
<show>away</show>
<status>開會中</status>
</presence>
<!-- 忙碌 -->
<presence>
<show>dnd</show> <!-- Do Not Disturb -->
<status>專注工作中</status>
</presence>
<!-- 離線 -->
<presence type="unavailable"/>Python 實作:
class MyBot(slixmpp.ClientXMPP):
async def start(self, event):
# 設定狀態
self.send_presence(pshow='away', pstatus='開會中')
# 監聽好友狀態
roster = await self.get_roster()
for jid in roster:
print(f"{jid}: {roster[jid]['presence']}")應用場景:
- 💬 聊天 App:顯示好友在線狀態
- 🎮 遊戲:顯示玩家在線/遊戲中
- 💼 協作工具:團隊成員狀態
- 📞 視訊會議:誰可以接聽
📝 總結
即時通訊協定就像不同的運輸工具:
- MQTT:機車 🏍️(輕巧靈活,適合短途)
- XMPP:汽車 🚗(舒適全面,適合日常)
- STOMP:腳踏車 🚲(簡單易用,適合新手)
- AMQP:卡車 🚚(可靠穩重,適合貨運)
根據你的需求選擇適合的協定,沒有最好的協定,只有最適合的!
記憶口訣:
- 「物聯 MQTT,聊天 XMPP,網頁 STOMP,企業 AMQP」
🔗 延伸閱讀
- 下一篇:05-2. MQTT 協定詳解
- 相關文章:04-1. WebSocket 基礎概念