MQTT填坑之旅

前言

最近两个项目中都采用了MQTT作为实时消息传输协议,在开发中遇到了不少问题,在这里简单的总结一下,以便记录和帮助大家少走弯路。这篇文章的内容主要来自于https://github.com/emqtt/emqttd 以及http://emqtt.com/

MQTT是什么

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和制动器(比如通过Twitter让房屋联网)的通信协议。

如何使用MQTT

服务端搭建

本部分将以EMQ为主要介绍对象,EMQ是一个百万级分布式开源物联网MQTT消息服务器。
如下图所示。
这里写图片描述
主要特点如下。

  • 完全开放源码
  • 百万级并发连接
  • 完整MQTT协议支持
  • 简便安装部署
  • 分布式集群或桥接
  • 扩展模块与插件

    EMQ的部署确实相当简单,特别对于windows用户,
    1.http://emqtt.com/downloads 下载windows版本,
    2.解压
    3.在bin目录下运行 emqttd start即可
    4.访问localhost:18083可以知道是否部署成功


tips:
1. EMQ的默认端口:8083 webSocket的端口,18083 工作台端口,1883 后台的通讯端口,8080 API端口
2. EMQ的开源版本是没有数据存储功能的,商业版本是具备数据存储的能力,商业版不便宜,最低的并发版本至少要3W/年。
3. EMQ的工作台是好东西,要充分利用,简单的测试都可以用它
4. EMQ的百万链接并非是并发,这个要注意。
5. MQTT是基于TCP,而MQTT-SN是基于UDP的。


关于数据存储是一个单独的话题,要是并发需求不高可以考虑自己搞一个,原理其实很简单。设定一个管理topic比如tempTopic,若某个topic的消息需要存储则将这个topic发送到tempTopic。再订阅这个topic并将收到的消息持久化即可。
简单流程如下所示
1.订阅tempTopic消息,若收到消息执行下面逻辑
2.订阅收到的消息内容的topic,并将消息内容持久化到数据库中,若收到消息执行下面逻辑
3.将消息内容持久化到数据库中。
4.系统启动时自动监听数据库中tempTopic的消息内容。

Web客户端使用

Web客户端其实就是JS客户端,主要可以用的是Eclipse Paho HTML5 JavaScript over WebSocket和MQTT.js
下面代码以MQTT.js和ES6为例。

import { connect } from 'mqtt';
var client  =  connect('ws://localhost:8083/mqtt');
client.on('connect', function () {
  client.subscribe('presence')
  client.publish('presence', 'Hello mqtt')
})

client.on('message', function (topic, message) {
  // message is Buffer
  console.log(message.toString())
  client.end()
})

Java客户端使用

Java客户端则以Eclipse Paho Java为主。

示例

import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.cert.CertificateException;

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

public class MqttPublishSample {

    public static void main(String[] args) throws KeyManagementException, CertificateException, FileNotFoundException, IOException, KeyStoreException {

        String topic        = "MQTT Examples";
        String content      = "Message from MqttPublishSample";
        int qos             = 2;
        String broker       = "ssl://localhost:8883";
        String clientId     = "JavaSample";
        MemoryPersistence persistence = new MemoryPersistence();

        try {
            MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
            MqttConnectOptions connOpts = new MqttConnectOptions();
            connOpts.setCleanSession(true);
            System.out.println("Connecting to broker: "+broker);
            sampleClient.connect(connOpts);
            System.out.println("Connected");
            System.out.println("Publishing message: "+content);
            MqttMessage message = new MqttMessage(content.getBytes());
            message.setQos(qos);
            sampleClient.publish(topic, message);
            System.out.println("Message published");
            client.setCallback(new MqttCallback() {
                public void connectionLost(Throwable throwable) {

                }

                public void messageArrived(String s, MqttMessage mqttMessage) throws  Exception {
  System.out.println("Message Arrived");
  System.out.println(new String(mqttMessage.getPayload(),"utf-8"));
                }

                public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {

                }
            });
            sampleClient.disconnect();
            System.out.println("Disconnected");
            System.exit(0);
        } catch(MqttException me) {
            System.out.println("reason "+me.getReasonCode());
            System.out.println("msg "+me.getMessage());
            System.out.println("loc "+me.getLocalizedMessage());
            System.out.println("cause "+me.getCause());
            System.out.println("excep "+me);
            me.printStackTrace();
        } 
    }
}

总结

1.clientId不能重复
2.需要数据存储功能的需要结合实际情况是自研还是购买服务
3.需要进行充分的测试,以避免Last Message引起的异常问题
4.对于是否能够满足性能需求一定要实际测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值