MQTT 和RocketMQ的区别:
1、传感器采用GPRS传输数据,采用微消息队列MQTT,微消息队列 MQTT 主要承担移动端连接接入、连接管理、数据转发等工作,相当于一个无限扩展能力的连接网关。传感器传送数据到阿里云Iot。MQTT支持Python,java,有相应的sdk,地址如下:
https://help.aliyun.com/product/100973.html?spm=a2c4g.11186623.6.540.791c5695zBTImA
阿里云Iot的设备传输数据格式是json格式,采用post方式提交数据,具体格式如下:
设备属性上报
通过该Topic获取设备上报的属性信息。
Topic:/sys/{productKey}/{deviceName}/thing/event/property/post
数据格式:
{
"iotId":"4z819VQHk6VSLmmBJfrf00107ee200",
"productKey":"1234556554",
"deviceName":"deviceName1234",
"gmtCreate":1510799670074,
"deviceType":"Ammeter",
"items":{
"Power":{
"value":"on",
"time":1510799670074
},
"Position":{
"time":1510292697470,
"value":{
"latitude":39.9,
"longitude":116.38
}
}
}
}
参数说明:
参数 | 类型 | 说明 |
---|---|---|
iotId | String | 设备在平台内的唯一标识 |
productKey | String | 设备所属产品的唯一标识 |
deviceName | String | 设备名称 |
deviceType | String | 设备类型 |
items | Object | 设备数据 |
Power | String | 属性名称,产品所具有的属性名称请参考TSL描述 |
Position | String | 属性名称,产品所具有的属性名称请参考TSL描述 |
value | 根据TSL定义 | 属性值 |
time | Long | 属性产生时间,如果设备没有上报默认采用云端生成时间 |
gmtCreate | Long | 数据流转消息产生时间 |
发送方式如下:
MQTT采用topic形式发送数据,生产者产生数据,通过topic进行发送,消费者订阅消息,接收消息。
2、MQTT将消息进行转储,使用RocketMQ进行转储,RocketMQ支持HTTP协议,有相应的sdk开发包,进行开发,如Python,java,通过ip地址直接订阅消息,地址如下:https://help.aliyun.com/product/29530.html?spm=a2c4g.11186623.6.540.71694fb3z3Z3Kg
RocketMQ是一个消息队列,吞吐性能强大。格式如下,
自定义生产者与消费者如下:
producer
发送消息
public class Producer {
public static void main(String[] args) throws MQClientException, InterruptedException {
DefaultMQProducer producer = new DefaultMQProducer("pay_topic_01");
producer.setNamesrvAddr("100.8.8.88:9876");
producer.start();
for (int i = 0; i < 1000; i++) {
try {
Message msg = new Message("TopicTest",// topic
"TagA",// tag
("Hello RocketMQ " + i).getBytes()// body
);
SendResult sendResult = producer.send(msg);
System.out.println(sendResult);
}
catch (Exception e) {
e.printStackTrace();
Thread.sleep(1000);
}
}
producer.shutdown();
}
}
订阅消息
public class Consumer {
public static void main(String[] args) throws InterruptedException, MQClientException {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name_4");
consumer.setNamesrvAddr("100.8.8.88:9876");
/**
* 设置Consumer第一次启动是从队列头部开始消费还是队列尾部开始消费
* 如果非第一次启动,那么按照上次消费的位置继续消费
*/
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
consumer.subscribe("TopicTest", "*");
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List
ConsumeConcurrentlyContext context) {
System.out.println(Thread.currentThread().getName() + " Receive New Messages: " + msgs);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
System.out.println("Consumer Started.");
}
3、阿里云官方Python 的sdk中的producer和consumer如下:
(1)producer
#初始化 client
mq_client = MQClient(
#设置HTTP接入域名(此处以公共云生产环境为例)
"${HTTP_ENDPOINT}",
#AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建
"${ACCESS_KEY}",
#SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建
"${SECRET_KEY}"
)
#所属的 Topic
topic_name = "${TOPIC}"
#Topic所属实例ID,默认实例为空None
instance_id = "${INSTANCE_ID}"
producer = mq_client.get_producer(instance_id, topic_name)
# 循环发布多条消息
msg_count = 100
print "%sPublish Message To %s\nTopicName:%s\nMessageCount:%s\n" % (10 * "=", 10 * "=", topic_name, msg_count)
try:
for i in range(msg_count):
msg_body = "I am test message %s." % i
msg = TopicMessage(
# 消息内容
"I am test message %s." % i,
# 消息标签
""
)
re_msg = producer.publish_message(msg)
print "Publish Message Succeed. MessageID:%s, BodyMD5:%s" % (re_msg.message_id, re_msg.message_body_md5)
time.sleep(1)
except MQExceptionBase, e:
if e.type == "TopicNotExist":
print "Topic not exist, please create it."
sys.exit(1)
print "Publish Message Fail. Exception:%s" % e
(2)consumer
重要的是message的body中的数据,取出数据即可实现通讯。
#初始化 client
mq_client = MQClient(
#设置HTTP接入域名(此处以公共云生产环境为例)
"${HTTP_ENDPOINT}",
#AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建
"${ACCESS_KEY}",
#SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建
"${SECRET_KEY}"
)
#所属的 Topic
topic_name = "${TOPIC}"
#您在控制台创建的 Consumer ID(Group ID)
group_id = "${GROUP_ID}"
#Topic所属实例ID,默认实例为空None
instance_id = "${INSTANCE_ID}"
consumer = mq_client.get_consumer(instance_id, topic_name, group_id)
#长轮询表示如果topic没有消息则请求会在服务端挂住3s,3s内如果有消息可以消费则立即返回
#长轮询时间3秒(最多可设置为30秒)
wait_seconds = 3
#一次最多消费3条(最多可设置为16条)
batch = 3
print "%sConsume And Ak Message From Topic%s\nTopicName:%s\nMQConsumer:%s\nWaitSeconds:%s\n" % (10 * "=", 10 * "=", topic_name, group_id, wait_seconds)
while True:
try:
#长轮询消费消息
recv_msgs = consumer.consume_message(batch, wait_seconds)
for msg in recv_msgs:
print "Receive, MessageId: %s\nMessageBodyMD5: %s \
\nMessageTag: %s\nConsumedTimes: %s \
\nPublishTime: %s\nBody: %s \
\nNextConsumeTime: %s \
\nReceiptHandle: %s" % \
(msg.message_id, msg.message_body_md5,
msg.message_tag, msg.consumed_times,
msg.publish_time, msg.message_body,//这里封装的数据问题
msg.next_consume_time, msg.receipt_handle)
except MQExceptionBase, e:
if e.type == "MessageNotExist":
print "No new message! RequestId: %s" % e.req_id
continue
print "Consume Message Fail! Exception:%s\n" % e
time.sleep(2)
continue
#msg.next_consume_time前若不确认消息消费成功,则消息会重复消费
#消息句柄有时间戳,同一条消息每次消费拿到的都不一样
try:
receipt_handle_list = [msg.receipt_handle for msg in recv_msgs]
consumer.ack_message(receipt_handle_list)
print "Ak %s Message Succeed.\n\n" % len(receipt_handle_list)
except MQExceptionBase, e:
print "\nAk Message Fail! Exception:%s" % e
#某些消息的句柄可能超时了会导致确认不成功
if e.sub_errors:
for sub_error in e.sub_errors:
print "\tErrorHandle:%s,ErrorCode:%s,ErrorMsg:%s" % (sub_error["ReceiptHandle"], sub_error["ErrorCode"], sub_error["ErrorMessage"])
具体的json数据解析请看另一篇文章:https://blog.csdn.net/u014535666/article/details/92848237
数据流转网址:https://help.aliyun.com/document_detail/73736.html?spm=a2c4g.11186623.6.599.3b4e2fcaPLzDhO
阿里物联网平台:https://iotnext.console.aliyun.com/lk/summary
消息服务控制台:https://mns.console.aliyun.com/?spm=5176.6660585.774526198.1.11946bf8o9CsYO#/logging/cn-beijing
微消息队列MQTT,消息队列RocketMQ:https://ons.console.aliyun.com/?spm=5176.11485173.0.0.23f759afSBZrGK#/?regionId=mq-internet-access