基於 WebSocket 的 MQTT 移動推送方案


WebSphere MQ Telemetry Transport 簡介

WebSphere MQ Telemetry Transport (MQTT) 是一項異步消息傳輸協議,是 IBM 在分析了他們的客戶在其業務中使用 WebSphere MQ 消息傳遞的情況(包括通過它傳遞數據)之后專門為物聯網所定制的重要的輕量級消息傳輸協議。IBM 發現,數據經常是在企業外部的遠程位置生成的,而且數據在從遠程位置到達企業之前通常要經歷一個復雜的過程。這時往往將數據人工輸入計算機,然后只能通過 WebSphere MQ Enterprise 消息傳遞系統傳輸。而 MQTT 的開發將 WebSphere MQ 消息傳遞的應用范圍延伸到這些遠程位置。

WebSphere MQ 遙測傳輸 (MQTT) 是輕量級基於代理的發布 / 訂閱的消息傳輸協議,設計思想是開放、簡單、輕量、易於實現。這些特點使它適用於受限環境。例如,但不僅限於此:

  • 網絡代價昂貴,帶寬低、不可靠。
  • 在嵌入設備中運行,處理器和內存資源有限。

該協議的特點有:

  • 使用發布 / 訂閱消息模式,提供一對多的消息發布,解除應用程序耦合。
  • 對負載內容屏蔽的消息傳輸。
  • 使用 TCP/IP 提供網絡連接。
  • 有三種消息發布服務質量:
    • "至多一次",消息發布完全依賴底層 TCP/IP 網絡。會發生消息丟失或重復。這一級別可用於如下情況,環境傳感器數據,丟失一次讀記錄無所謂,因為不久后還會有第二次發送。
    • "至少一次",確保消息到達,但消息重復可能會發生。
    • "只有一次",確保消息到達一次。這一級別可用於如下情況,在計費系統中,消息重復或丟失會導致不正確的結果。
  • 小型傳輸,開銷很小(固定長度的頭部是 2 字節),協議交換最小化,以降低網絡流量。
  • 使用 Last Will 和 Testament 特性通知有關各方客戶端異常中斷的機制。

推送服務

推送服務表現為客戶端能自動收到服務器發送過來的數據和信息。其目的都是為了給最終客戶方便有效地發送最新消息或者數據。而且推送的模式對以前的數據訪問方式提供很好的補充和發展。首先,給最終用戶帶來了很好的使用體驗,可以實時的獲取自己感興趣的信息,與此同時,給服務器端的應用商,也提供了更為便捷和主動的數據,服務發布方式,使得應用商能夠控制信息發布的頻率和時間,從而能更精准的投送的最終用戶。

推送服務本質上是服務器主動將消息,數據發送到客戶端,而不是客戶端主動去服務器請求數據。這種推送只需要客戶端與服務器連接后,在有數據的情況下,服務器端馬上將數據發送到客戶端。這里的客戶端可以是多種類型的,比如比較常見的瀏覽器,移動應用等等。

推送服務的實現方式大致可分為 Poll 和 Push 模式。

  • Poll 模式

    Poll 模式,本質上是"偽推送"模式,或者叫短輪詢模式。是客戶端通過設定固定的時間間隔,然后在時間間隔到達后,客戶端主動向服務器發送請求,去更新是否有新數據。這種模式的特點是,客戶端需要不停的輪詢訪問服務器獲取信息,其時間間隔設定無法真正體現實時推送,間隔太長容易導致信息不能實時的更新,間隔太短,客戶端需要發送很多不必要的連接請求,耗費很多網絡流量和服務器開銷。比如在移動終端上,此類模式會在設備電能消耗,網絡流量使用方面存在很多瓶頸。

  • Push 模式

    Push 模式,一般意義上使用長連接去建立一個客戶端到服務器的雙向數據通道,只要在連接建立后,一旦一方有數據更新,就可以馬上通過雙向的數據通道向對方發送數據,平時在沒有數據時,通過一些心跳等機制維持通道連接。Push 模式的特點,簡化的客戶端的開發,數據能近乎實時的發送到對方。但其在設備資源消耗和網絡流量控制方面,根據其使用的不同協議會有很大不同,特別是在移動推送領域,長連接對移動設備電量和網絡流量的消耗要求較高。同時,由於需要維護長連接,對服務器在高並發連接的處理能力和性能也有很高要求。

移動推送服務

推送服務在很多領域都有發展,但特別在移動領域,由於其飛速發展,給推送服務帶來了很多新的機遇和挑戰。首先,移動市場規模越來越大,終端種類和數量越來越多,使得推送服務的的重要性越來越凸顯;其次,傳統的"偽推送"模式已越來越不能滿足其需要,需要發展新的推送的技術,這促使了很多新的協議和框架的出現;但是,由於移動領域的終端設備和網絡情況的特點,對推送的協議和框架又提出了新的挑戰,比如:移動終端的計算和存儲資源的限制,移動終端的電量消耗的限制,移動網絡流量和成本的控制等等。主流的移動推送解決方案如下:

  • SMS 短信

    作為傳統的消息通訊,在新型移動環境下,在網絡成本方面的考量使其地位有逐漸邊緣化的趨勢。

  • HTTP 輪詢

    使用定時的 HTTP 輪詢方式,及客戶端在一定的時間間隔里去重復向服務器請求數據更新,屬於"偽推送",由於其協議復雜冗余,輪詢間隔的不准確,耗費了不必要的流量,增加了終端用戶網絡成本等因素,現有的這種方式已經不適合做移動推送服務。

  • XMPP

    XMPP 是基於 XML 的通訊協議,此協議已基本上完成了標准化,成熟,強大,可擴展性強。但正是由於其協議復雜,冗余的設計,成為其在移動設備上短板,比如協議的復雜帶來其協議棧的耗電增加,冗余的設計使得網絡流量偏大,用戶成本增加。

  • 私有廠商協議和平台

    私有廠商推出的推送服務,由於其協議私有,其傳輸效率和質量上無法量化和考證,而且還往往無法實現跨平台推送。同時,有些廠商提供的消息服務器不具備公開性,導致在用戶數據安全性特別是服務器掌控方面存在擔心。

IBM 基於 WebSocket 的 MQTT 跨平台推送服務方案

IBM 通過對現有移動推送平台比較之后,對其中存在的問題和缺陷做了很好的分析。這些問題集中體現在如下方面:

  • 在網絡方面

    如何適應現有網絡的不可靠,很好的保障數據發送可靠性

    如何降低網絡流量,從而節省網絡成本

  • 在移動設備方面

    如何降低對設備能力的要求,特別是適應計算和存儲弱的設備

    如何降低對設備電量的消耗,滿足設備電源能力的不足

    如何降低平台依賴性,真正實現跨移動設備平台

  • 在數據方面

    缺少對數據安全性的保障,特別是對服務器的掌控

    缺少對大量數據的監測,優化

IBM 針對上面問題,結合 MQTT 和 WebSocket,提出了更智慧的移動推送服務解決方案。

圖 1. IBM 移動推送服務解決方案

圖 1. IBM 移動推送服務解決方案

方案中,服務器端使用 WebSphere MQ 作為 MQTT 的 Server,在移動設備中嵌入 MQTT 的客戶端,並通過客戶端建立到服務器的雙向數據通道,然后在后台來自不同應用的數據通過 WebSphere MQ 推送到移動終端。那么,這樣的解決方案,會有什么特點能夠很好的解決和優化上面關於業界移動推送服務解決方案中存在的普遍問題,或者說此方案有什么自身的優勢。

  • 移動設備

    能在 8bit 位處理器上很好的運行 C /JavaScript/Java 的 client 庫分別只有 30/75/100KB

    在移動設備上耗電率低,大約只需要 HTTP 的一半

    通過使用基於 WebSocket 的 MQTT 客戶端 JavaScript API,符合 Hybrid 開發潮流,只要設備的瀏覽器支持 WebSocket,就能很輕松實現多移動平台的跨越

  • 很好的適應各種復雜網絡,特別是受限網絡

    預期並適應頻繁的網絡中斷,能應對低速、低質量的網絡

    壓縮優化過后的協議,可以有效降低網絡流量,從而節約網絡成本

    完成同樣的數據通信,MQTT 只需要 HTTP 約 1/4 得數據流量

  • 發布 - 訂閱的消息通信協議,允許一條消息只發布一次,便可被多個消費端(應用程序 / 設備)所接收

    實現系統間松耦合,簡化開發,方便擴展,整合。

  • 提供靈活便捷的系統整合能力

    使用 MQ,MB 提供可靠系統內系統整合和通信

    Cast Iron 強大的系統間整合帶來巨大的靈活性

  • 提供豐富的安全性

    使用 SSL 提供的認證和加密來保證傳輸安全性

    通過 JAAS 接口提供的身份認證

    OAM 用於資源層面的授權

  • 強大的性能提高系統的高可靠性

    高連接數下系統低計算資源使用

    高連接數下系統高信息處理速度

  • 提供多種消息服務質量,滿足不同場景需求

    0 :消息最多被傳遞一次,比如一般類廣告,通知

    1 :消息會被傳遞但可能會重復傳遞,比如賬戶余額通知

    2 :消息保證傳遞且僅有一次傳遞,比如交易支付批復通知

應用場景

本文是通過介紹使用 WebSphere MQ Telemetry 以及其 SDK 組件中自帶的 MQTT 基本客戶端(WebSocket API)實現一個 iOS 設備的推送應用場景,來使讀者對使用基於 MQTT 協議的 WebSphere MQ Telemetry 來構建物移動推送服務解決方案有進一步的理解,並能夠自己動手開發相應的解決方案。

該方案通過 WebSphere MQ Telemetry 自帶的 MQTT 基本客戶機 WebSocket JavaScript API 來實現客戶端到服務器的連通。實現的場景如下:

  • Mobile 用戶相互通訊(文本,語音,圖片)
  • 后台應用向 Mobile 用戶推送相關信息(廣告,通知等等)
圖 2. 移動推送服務場景

圖 2. 移動推送服務場景

開發步驟及流程

整個開發會涉及到移動端開發和服務器端配置,以下將會分別介紹。

Note:開發工具使用 Worklight,Xcode,WebSphere MQ Explorer。

客戶端開發

Worklight 平台為開發基於 Web 技術的手機客戶端 App 提供了一套完整的解決方案,從開發、部署、測試到發布均可在這個平台上完成。App 用 HTML,CSS 和 Javascript 寫成,之后被擴展成桌面的(Windows,Mac,Linux),互聯網的(Facebook 等),本地移動設備上的(iOS,Android,RIM 和 Windows Phone)應用程序。開發者還能把一些流行的 Javascript 構架如 jQuery Mobile,Sencha 和 Dojo 整合到 Worklight 中。而且 App 的本地運行時也能用本地代碼來編寫和修改。

MQTT WebSocket JavaScript API 的功能描述如下:

  • Connect 連接

    MQTT 客戶端負責向 MQTT 服務器發起連接操作,並開始計時,在超時期里接收到正確連接響應,則連接成功,負責連接超時。任何數據的發送或者收到,都將啟動新的超時計時,在整個超時完成后沒有數據的發送或者接收時,發送心跳以維持連接狀態。

  • DisConnect 斷開連接

    MQTT 客戶端或者服務器發起連接斷開命令。在發出連接斷開命令后,開始超時計時,在超時內成功收到斷開響應,雙方設置其相應連接狀態為斷開;超時后尚未成功接收響應,則開始重發連接命令,直到重發次數到達系統設置上限。否則,設置對應原因。

  • Subscribe 訂購

    在雙方連接建立后,MQTT 客戶端發送訂購消息,來訂購主題,並設置相應質量服務級別,在接收到訂購確認后,自動接收在此主題上的任何消息。

  • UnSubscribe 取消訂購

    在雙方連接建立后,MQTT 客戶端發送取消訂購消息,來取消訂購主題,在接收到取消訂購確認后,在原來主題上的任何消息將不再推送到此客戶端。

  • Publish 發布

    在雙方連接建立后,MQTT 客戶端將業務數據放入發布消息的消息體中,通過發布消息,發布在某主題上,此消息按照不同的消息服務質量級別,發布到不同的訂購者客戶端。

  • Will 主題和消息

在 MQTT 客戶端連接時設置,設定在自己連接中斷后,自動往 Will 主題上發送的通知消息。

  1. 在 Worklight Studio 中新建 Worklight Project,在工程名中填入 WebSocketMQTT,然后選擇 Hybrid Application,點擊下一步,在應用名中填入 WebSocketMQTTApp,點擊完成。
    圖 3. WorkLight 工程
    圖 3. WorkLight 工程
  2. 在工程上單擊右鍵,選擇新建 Worklight Environment。Project 選擇剛生成的 WebSocketMQTT,Application 選擇剛生成的 WebSocketMQTTApp,然后在 Mobile 中選擇"iPad"選項框。最后點擊完成。
    圖 4. 新建 Worklight Environment
    圖 4. 新建 Worklight Environment

    然后在工程中就生成的為 iPad 開發的模板。

    圖 5. iPad 開發模板
    圖 5. iPad 開發模板
  3. 將 MQTT 的基於 WebSocket 的 Client API 拷貝到 iPad 下的 js 文件夾。
    圖 6. 拷貝 MQTT Client 的 JS 庫文件
    圖 6. 拷貝 MQTT Client 的 JS 庫文件
  4. 從本文附件中導入並替代展現頁面 WebSocketMQTTApp.html 到 common 文件夾。
    圖 7. 替換原有展現頁面
    圖 7. 替換原有展現頁面

    然后在 application:WebSocketMQTTApp 上右鍵,選擇 Run As -> Build All and Deploy

  5. 在 iPad 模板圖標上右鍵,選擇 Run As -> Xcode project。
    圖 8. 打開 Xcode Project
    圖 8. 打開 Xcode Project

在 Xcode 里,在 Build 成功后,選擇配置過的 iOS 設備安裝。

服務器開發和配置

安裝 WebSphere MQ 7.5.0.1 版本,在安裝過程中選擇 Telemetry 組件,安裝完后打開 WebSphere MQ 管理界面 WebSphere MQ Explorer。

  1. 打開 WebSphere MQ Explorer
    圖 9. WebSphere MQ Explorer
    圖 9. WebSphere MQ Explorer
  2. 在 Queue Managers 上右鍵,選擇新建 Queue Manager,輸入 Queue Manager 名稱,然后 Next 直到 Finish。

    展開新創建的 Queue Manager,點擊 Telemetry 並在右邊的窗口中,選擇 Define sample configuration...

    圖 10. 定義 Telemetry 服務
    圖 10. 定義 Telemetry 服務
    圖 11. 配置 Telemetry
    圖 11. 配置 Telemetry
  3. 在配置部署后,會在 Services 中創建並啟動服務:SYSTEM.MQXR.SERVICE 同時展開 Telemetry 后在 Channels 里創建了一個接受 MQTT 連接的 PlainText 通道,端口默認是 1883。
    圖 12. 支持 MQTT 連接的通道
    圖 12. 支持 MQTT 連接的通道
  4. 最后為了測試數據的收發,可以打開 WebSphere MQ 自帶的測試工具:MQTT Client Utility。
    圖 13. MQTT Client Utility 工具
    圖 13. MQTT Client Utility 工具

服務器端的配置就完成了。

部署和驗證

本文將通過模擬移動推送服務中的 2 個基本場景來驗證。

  • 兩個 iPad 設備通訊模擬 Mobile 用戶相互通訊
  • MQTT Client Utility 向 iPad 發送消息模擬后台應用向 Mobile 用戶推送相關信息
  1. 在兩台 iPad 上安裝我們剛剛開發的 App,並配置如下參數:
    • Server:WebSphere MQ 的安裝機器的 IP
    • Port:在 WebSphere MQ 里配置的 MQTT 的通道的端口號,默認是 1883
    • Client ID:頁面會生成一個默認的,也可以自定義
    • Topic Name:用於發布或者訂購的主題,模擬通訊時,每個客戶端有固定的主題,比如:iPad A 主題為 iPadA,iPad B 的主題為 iPadB。在通訊時每個客戶端訂購自己的主題接收別的客戶端發送來的消息,同時給別的客戶端的主題發送消息。
    • QoS:質量服務等級

    啟動 App 后,在填寫 Server,port 和 Client Id 后,點擊連接(Connect),然后分別在訂閱的 Topic Name 中填寫自己要監聽的主題:iPadA 或者 iPadB。最后,在發布 Publish 的 Topic 中填入要對話的對方的主題:iPadB 或者 iPadA,輸入想發送的信息后,點擊發送就可以開始兩個 iPad 之間的通訊了。這里只是簡單展現,除了文本通訊還可以實現語音,文件,照片通訊分享等。

    圖 14. iPadA
    圖 14. iPadA
    圖 15. iPadB
    圖 15. iPadB

    通過以上兩個截圖,驗證了兩個 iPad 通過基於 WebSocket 的 MQTT 協議,實現了通訊,相互給對方發送了消息。

    Note: 在 App 部署到 iPad 上后,如果 WorkLight 的服務器更換了,修改應用的 WorkLight Server 地址如下

    圖 16. 應用的 WorkLight 服務器地址
    圖 16. 應用的 WorkLight 服務器地址
  2. 為了模擬服務器端應用向移動終端推送消息,采用 JMS 模式通過 WebSphere MQ 向終端推送一條數據。
    • Topic Name:iPadPush
    • Message:This is message from backend system application.
    后端采用 JMS 方式發送數據
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    import javax.jms.Connection;
    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.MessageProducer;
    import javax.jms.Session;
    import com.ibm.mq.jms.MQConnectionFactory;
    public class JMSSender {
         private Connection conn;
         private Session sess;
         private MessageProducer sender;
         public static void main(String[] args) {
             JMSSender jmsSender = new JMSSender();
             jmsSender.createSender();
             jmsSender.closeSender();
         }
         private void closeSender() {
             try {
    sender.close();
    sess.close();
    conn.close();
    System.out.println("JMS Sender closed");
             } catch (JMSException e) {
    e.printStackTrace();
    if (e.getLinkedException() != null) {
         e.getLinkedException().printStackTrace();
    }
             }
         }
         private void createSender() {
             MQConnectionFactory connFact = new MQConnectionFactory();
             try {
    // We are connecting to queue manager using client mode
    connFact.setQueueManager("XRNEW");
    connFact.setHostName("localhost");
    connFact.setPort(1414);
    System.out.println("Model"+connFact.getTransportType());
    //connFact.setTransportType(1);
    System.out.println("Model"+connFact.getTransportType());
    conn = connFact.createConnection();
    sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
    sender = sess.createProducer(sess
             .createQueue("queue://iPadA/iPadPush"));
    Message msg = sess.createTextMessage(
            "This is message from backend system application.");
    msg.setJMSExpiration(10000);
    sender.setTimeToLive(10000);
    sender.send(msg);
    System.out
             .println("JMS Sender started and published message to topic iPadPush");
             } catch (JMSException e) {
    e.printStackTrace();
    if (e.getLinkedException() != null) {
         e.getLinkedException().printStackTrace();
    }
             }
         }
    }
    圖 17. 終端接收后端推送的消息
    圖 17. 終端接收后端推送的消息

結束語

本文通過介紹使用 WebSphere MQ Telemetry 以及其 SDK 組件中自帶的 MQTT 基本客戶機的 WebSocket JavaScript API 開發一個 App,並通過實現通用的移動推送服務應用場景來使讀者對使用基於 MQTT 協議的 WebSocket JavaScript API 來構建移動推送服務解決方案有進一步的理解,並能夠自己動手開發相應的推送解決方案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM