用戶屬性 - MQTT 5.0 新特性

MQTT v5 帶來了很多新的特性,我們會盡量以通俗易懂的方式展示這些特性,並探討這些特性對開發者的影響。到目前爲止,我們已經探討過這些 MQTT v5 新特性,今天我們將繼續討論: 用戶屬性

什麼是用戶屬性

用戶屬性(User Properties)其實是一種自定義屬性,允許用戶向 MQTT 消息添加自己的元數據,傳輸額外的自定義信息以擴充更多應用場景。

它由一個用戶自定義的 UTF-8 的鍵/值對數組組成,並在消息屬性字段中配置,只要不超過最大的消息大小,可以使用無限數量的用戶屬性來向 MQTT 消息添加元數據,並在發佈者、MQTT 服務器和訂閱者之間傳遞信息。

如果你熟悉 HTTP 協議的話,該功能與 HTTP 的 Header 的概念非常類似。用戶屬性有效地允許用戶擴展 MQTT 協議,並且可以出現在所有消息和響應中。因爲用戶屬性是由用戶定義的,它們只對該用戶的實現有意義。

爲什麼需要使用用戶屬性

MQTT 3 的協議擴展性能力較差,用戶屬性其實就是爲了解決這個問題,它支持在消息中傳遞任何信息,確保了用戶可擴展標準協議的功能。

對於選擇和配置不同的消息類型,用戶屬性可以在客戶端與 MQTT 服務器之間,或者客戶端和客戶端之間發送。在連接客戶端中配置用戶屬性時,只能在 MQTT 服務器上接收,無法在客戶端中接收。如果在發送消息的時候配置用戶屬性,則可以在其它客戶端中接收。常用的有以下兩種用戶屬性配置。

連接客戶端的用戶屬性

當客戶端與 MQTT 服務器發起連接時,服務器可以預先定義好一些需要並且可以使用到的元數據信息,即用戶屬性,當連接成功後,MQTT 服務可以拿到連接發送過來的相關信息進行使用,因此連接客戶端的用戶屬性依賴於 MQTT 服務器。

消息發佈的用戶屬性

消息發佈時的用戶屬性可能是較爲常用的,因爲它們可以在客戶端與客戶端之間進行元數據信息傳遞。比如可以在發佈時添加一些常見的信息:消息編號,時間戳,文件,客戶端信息和路由信息等屬性。

除上述較爲常用的用戶屬性設置外,還可以在訂閱 Topic 時,取消訂閱時,斷開連接時配置用戶屬性。

用戶屬性的使用

文件傳輸

MQTT 5 的用戶屬性,可擴展爲使用其進行文件傳輸,而不是像之前的 MQTT 3 中將數據放到消息體的 Payload 中,用戶屬性使用鍵值對的方式。這也意味着文件可以保持爲二進制,因爲文件的元數據在用戶屬性中。例如:

{
  "filename": "test.txt",
  "content": "xxxx"
}

資源解析

當客戶端連接到 MQTT 服務器後,不同的客戶端、供應商平臺或系統存在着不同的方式傳遞消息數據,消息數據的格式可能都存在着一些結構差異。還有一些客戶端是分佈在不同的地域下。比如:地域 A 的設備發送的消息格式是 JSON 的,地域 B 的設備發送的是 XML 的,此時服務器接收到消息後可能需要一一進行判斷和對比,找到合適的解析器來進行數據解析。

此時爲了提高效率和減少計算負載,我們可以利用用戶屬性功能來添加數據格式信息和地域信息,當服務器接收到消息後,可以使用用戶屬性中提供的元數據來進行數據解析操作。並且當區域 A 的客戶端訂閱接收到來自區域 B 的客戶端消息時,也能快速的清楚特定的消息的來自於哪個區域等,從而使的消息具有了可追溯性。

{
  "region": "A",
  "type": "JSON"
}

MQTT 資源解析

消息路由

我們還可以使用用戶屬性來做應用層級別的路由。如上所述,存在着不同的系統和平臺,每個區域存在着不同的設備,多個系統可能收到同一個設備的消息,有些系統需要將數據進行實時的展示,另一個系統可能將這些數據進行時序存儲。因此 MQTT 服務器可以通過上報消息中配置的用戶屬性來確定將消息分發到存儲消息的系統還是展示數據的系統。

{
  "type": "real-time",
  "timestamp": 1636620444
}

MQTT 消息路由

在客戶端中配置用戶屬性

我們以 JavaScript 環境爲例,使用 MQTT.js 客戶端來進行編程。

注意:在連接客戶端時需指定 MQTT 的版本 protocolVersion 爲 5。

連接

我們在連接時的 options 中設置 properties 的 User Properties 屬性,添加 type 和 region 屬性。連接成功後,MQTT 服務器將收到這個用戶自定義的信息。

// connect options
const OPTIONS = {
  clientId: 'mqtt_test',
  clean: true,
  connectTimeout: 4000,
  username: 'emqx',
  password: 'public',
  reconnectPeriod: 1000,
  protocolVersion: 5,
  properties: {
    userProperties: {
      region: 'A',
      type: 'JSON',
    },
  },
}
const client = mqtt.connect('mqtt://broker.emqx.io', OPTIONS)

發佈消息

連接成功後發佈消息,發佈消息的配置中設置用戶屬性,並且監聽消息接收。在 publish 函數中,我們配置 user properties 屬性,並在接收消息的函數中打印 packet。

client.publish(topic, 'nodejs mqtt test', {
  qos: 0,
  retain: false,
  properties: {
    userProperties: {
      region: 'A',
      type: 'JSON',
    },
  },
}, (error) => {
  if (error) {
    console.error(error)
  }
})
client.on('message', (topic, payload, packet) => {
  console.log('packet:', packet)
  console.log('Received Message:', topic, payload.toString())
})

此時我們看到控制檯中已經打印並輸出了剛纔發送時所配置的用戶屬性。

MQTT 消息接收

對於其它客戶端,我們將在跨平臺 MQTT 5.0 桌面客戶端工具 - MQTT X 的後續版本中支持用戶屬性的自定義配置,方便用戶快速測試 MQTT 5.0 的一些新特性,敬請期待!

版權聲明: 本文爲 EMQ 原創,轉載請註明出處。

原文鏈接:https://www.emqx.com/zh/blog/mqtt5-user-properties

技術支持:如對本文或 EMQ 相關產品有疑問,可訪問 EMQ 問答社區 https://askemq.com 提問,我們將會及時回覆支持。

更多技術乾貨,歡迎關注我們公衆號【EMQ 中文社區】。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章