阿里云物联网平台服务端订阅之AMQP

简介: 服务端可以直接订阅产品下所有类型的消息:设备上报消息、设备状态变化通知、网关发现子设备上报、设备生命周期变更、设备拓扑关系变更。配置服务端订阅后,物联网平台会将产品下所有设备的已订阅类型的消息转发至您的服务端。AMQP(Advanced Message Queuing Protocol)即高级消息队列协议。您配置AMQP服务端订阅后,物联网平台会将产品下所有已订阅类型的消息,通过AMQP通道推送至您的服务端。

概述

服务端可以直接订阅产品下所有类型的消息:设备上报消息、设备状态变化通知、网关发现子设备上报、设备生命周期变更、设备拓扑关系变更。配置服务端订阅后,物联网平台会将产品下所有设备的已订阅类型的消息转发至您的服务端。
AMQP(Advanced Message Queuing Protocol)即高级消息队列协议。您配置AMQP服务端订阅后,物联网平台会将产品下所有已订阅类型的消息,通过AMQP通道推送至您的服务端。
本文通过MQTT.fx模拟设备接入,MQTT.fx接入物联网平台。通过Java SDK进行服务端订阅演示,SDK下载地址

消息流转示意图

image

AMQP服务端订阅优势

  • 支持多消费组。同一个账号,可以在开发环境下使消费组A订阅产品A,同时在正式环境下使消费组B订阅产品B。
  • 方便排查问题。支持查看客户端状态、查看堆积和消费速率。
  • 线性扩展。在消费者能力足够,即客户端机器足够的情况下,可轻松线性扩展推送能力。
  • 实时消息优先推送,消息堆积不会影响服务。设备实时消息直接推送,推送限流或失败时进入堆积队列,堆积态消息采用降级模式,不会影响实时推送能力。即使消费者的客户端宕机,或因消费能力不足堆积了消息,消费端恢复后,设备生成的消息也可以和堆积消息并行发送,使设备优先恢复可用态。

操作流程

1.在物联网平台的控制台上创建对应产品的AMQP服务端订阅,并勾选需要推送的消息类型
image

2.填写相关参数,并启动消费端。参数说明

  • 添加依赖如下:
    <dependencies>
        <!-- amqp 1.0 qpid client -->
        <dependency>
            <groupId>org.apache.qpid</groupId>
            <artifactId>qpid-jms-client</artifactId>
            <version>0.47.0</version>
        </dependency>
        <!-- util for base64-->
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.10</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.22</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.22</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.7.2</version>
        </dependency>
    </dependencies>
  • 代码示例如下:
import java.net.URI;
import java.util.Hashtable;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.apache.commons.codec.binary.Base64;
import org.apache.qpid.jms.JmsConnection;
import org.apache.qpid.jms.JmsConnectionListener;
import org.apache.qpid.jms.message.JmsInboundMessageDispatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AmqpJavaClientDemo {

    private final static Logger logger = LoggerFactory.getLogger(AmqpJavaClientDemo.class);

    public static void main(String[] args) throws Exception {
        //参数说明,请参见上一篇文档:AMQP客户端接入说明。
        String accessKey = "******";
        String accessSecret = "******";
        String consumerGroupId = "******";
        long timeStamp = System.currentTimeMillis();
        //签名方法:支持hmacmd5,hmacsha1和hmacsha256
        String signMethod = "hmacsha1";
        //控制台服务端订阅中消费组状态页客户端ID一栏将显示clientId参数。
        //建议使用机器UUID、MAC地址、IP等唯一标识等作为clientId。便于您区分识别不同的客户端。
        String clientId = "******";

        //UserName组装方法,请参见上一篇文档:AMQP客户端接入说明。
        String userName = clientId + "|authMode=aksign"
                + ",signMethod=" + signMethod
                + ",timestamp=" + timeStamp
                + ",authId=" + accessKey
                + ",consumerGroupId=" + consumerGroupId
                + "|";
        //password组装方法,请参见上一篇文档:AMQP客户端接入说明。
        String signContent = "authId=" + accessKey + "&timestamp=" + timeStamp;
        String password = doSign(signContent,accessSecret, signMethod);
        //按照qpid-jms的规范,组装连接URL。
        String connectionUrl = "failover:(amqps://${UID}.iot-amqp.cn-shanghai.aliyuncs.com:5671?amqp.idleTimeout=80000)"
                + "?failover.maxReconnectAttempts=10&failover.reconnectDelay=30";

        Hashtable<String, String> hashtable = new Hashtable<>();
        hashtable.put("connectionfactory.SBCF",connectionUrl);
        hashtable.put("queue.QUEUE", "default");
        hashtable.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContextFactory");
        Context context = new InitialContext(hashtable);
        ConnectionFactory cf = (ConnectionFactory)context.lookup("SBCF");
        Destination queue = (Destination)context.lookup("QUEUE");
        // Create Connection
        Connection connection = cf.createConnection(userName, password);
        ((JmsConnection) connection).addConnectionListener(myJmsConnectionListener);
        // Create Session
        // Session.CLIENT_ACKNOWLEDGE: 收到消息后,需要手动调用message.acknowledge()
        // Session.AUTO_ACKNOWLEDGE: SDK自动ACK(推荐)
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        connection.start();
        // Create Receiver Link
        MessageConsumer consumer = session.createConsumer(queue);
        consumer.setMessageListener(messageListener);
    }

    private static MessageListener messageListener = new MessageListener() {
        @Override
        public void onMessage(Message message) {
            try {
                byte[] body = message.getBody(byte[].class);
                String content = new String(body);
                String topic = message.getStringProperty("topic");
                String messageId = message.getStringProperty("messageId");
                logger.info("receive message"
                        + ", topic = " + topic
                        + ", messageId = " + messageId
                        + ", content = " + content);
                System.out.println("topic:" + topic);
                System.out.println("payload:" + content);
                System.out.println(" ");
                //如果创建Session选择的是Session.CLIENT_ACKNOWLEDGE,这里需要手动ACK。
                message.acknowledge();
                //如果要对收到的消息做耗时的处理,请异步处理,确保这里不要有耗时逻辑。
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    private static JmsConnectionListener myJmsConnectionListener = new JmsConnectionListener() {
        /**
         * 连接成功建立。
         */
        @Override
        public void onConnectionEstablished(URI remoteURI) {
            logger.info("onConnectionEstablished, remoteUri:{}", remoteURI);
        }

        /**
         * 尝试过最大重试次数之后,最终连接失败。
         */
        @Override
        public void onConnectionFailure(Throwable error) {
            logger.error("onConnectionFailure, {}", error.getMessage());
        }

        /**
         * 连接中断。
         */
        @Override
        public void onConnectionInterrupted(URI remoteURI) {
            logger.info("onConnectionInterrupted, remoteUri:{}", remoteURI);
        }

        /**
         * 连接中断后又自动重连上。
         */
        @Override
        public void onConnectionRestored(URI remoteURI) {
            logger.info("onConnectionRestored, remoteUri:{}", remoteURI);
        }

        @Override
        public void onInboundMessage(JmsInboundMessageDispatch envelope) {}

        @Override
        public void onSessionClosed(Session session, Throwable cause) {}

        @Override
        public void onConsumerClosed(MessageConsumer consumer, Throwable cause) {}

        @Override
        public void onProducerClosed(MessageProducer producer, Throwable cause) {}
    };

    /**
     * password签名计算方法,请参见上一篇文档:AMQP客户端接入说明。
     */
    private static String doSign(String toSignString, String secret, String signMethod) throws Exception {
        SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), signMethod);
        Mac mac = Mac.getInstance(signMethod);
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(toSignString.getBytes());
        return Base64.encodeBase64String(rawHmac);
    }
}

3.启动消费端后,在控制台进行查看
image

4.设备上线并上报一条消息
image

5.服务端查看订阅的消息
image

说明

  • 消息不保序。您可以使用时间戳来实现业务的相对有序。
  • 消息可能重复发送。为了确保消息送达,在某些情况下,同一条消息可能重复发送,直到客户端返回ACK或消息过期。您可以根据消息ID做唯一性处理。
  • 堆积清理。可在客户端设置cleanSession,每次上线清空堆积消息。
相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
目录
相关文章
|
6月前
|
消息中间件 DataWorks 物联网
MQTT问题之接入阿里云物联网平台如何解决
MQTT接入是指将设备或应用通过MQTT协议接入到消息服务器,以实现数据的发布和订阅;本合集着眼于MQTT接入的流程、配置指导以及常见接入问题的解决方法,帮助用户实现稳定可靠的消息交换。
421 1
|
1月前
|
存储 边缘计算 物联网
阿里云物联网平台:推动万物互联的智能化解决方案
随着物联网技术的快速发展,阿里云物联网平台为企业提供了一体化的解决方案,包括设备接入、数据管理和智能应用等核心功能。平台支持海量设备接入、实时数据采集与存储、边缘计算,并具备大规模设备管理、高安全性和开放生态等优势。广泛应用于智能制造、智慧城市和智能家居等领域,助力企业实现数字化转型。
156 5
|
3月前
|
消息中间件 传感器 监控
AMQP 与物联网 (IoT) 应用的结合
【8月更文第28天】高级消息队列协议 (AMQP) 是一种开放标准的应用层协议,特别适合于物联网 (IoT) 场景中的消息传递。AMQP 提供了可靠的、可扩展的消息传输机制,能够处理来自大量设备的数据流。本文将探讨 AMQP 在 IoT 应用中的优势,并提供使用不同编程语言构建 AMQP 客户端的具体示例。
86 0
|
4月前
|
存储 运维 监控
阿里云物联网平台的优势
【7月更文挑战第19天】阿里云物联网平台的优势
75 1
|
4月前
|
消息中间件 物联网 API
消息队列 MQ使用问题之如何在物联网项目中搭配使用 MQTT、AMQP 与 RabbitMQ
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
6月前
|
Cloud Native 安全 物联网
【阿里云云原生专栏】云边端一体化:阿里云如何利用云原生技术赋能物联网
【5月更文挑战第22天】阿里云借助云原生技术赋能物联网,实现云边端一体化,提升系统弹性与敏捷性。通过容器化部署,保证高可用性与可靠性。在智能交通等领域,阿里云提供高效解决方案,实现实时数据分析与决策。代码示例展示如何使用阿里云服务处理物联网数据。同时,阿里云重视数据安全,采用加密和访问控制保障数据隐私。丰富的工具和服务支持开发者构建物联网应用,推动技术广泛应用与发展。
371 1
|
6月前
|
消息中间件 存储 JavaScript
阿里云IOC物联网异步处理基础概念
该内容介绍了异步处理基础和消息队列的相关概念。首先,同步处理指任务完成后才能执行其他操作,而异步则允许任务并行执行,不阻塞程序。异步能提高系统并发性和响应性,但也增加复杂性和资源消耗。接着,提到了消息队列,包括生产者、消费者、队列、broker和topic等概念,并指出在IoT中,设备作为生产者发送消息到特定topic,消费者从队列获取数据。最后,简要介绍了AMQP协议,它是用于应用程序间消息传递的开放标准,常用于分布式系统和物联网,如RabbitMQ和Apache Qpid。课程将以Apache Qpid为例接收IoT数据。
225 6
阿里云IOC物联网异步处理基础概念
|
6月前
【开源视频联动物联网平台】vertx写一个mqtt服务端
【开源视频联动物联网平台】vertx写一个mqtt服务端
137 1
|
6月前
|
消息中间件 网络协议 物联网
MQTT协议问题之阿里云物联网服务器断开如何解决
MQTT协议是一个轻量级的消息传输协议,设计用于物联网(IoT)环境中设备间的通信;本合集将详细阐述MQTT协议的基本原理、特性以及各种实际应用场景,供用户学习和参考。
487 1
|
4天前
|
存储 安全 物联网
政府在推动物联网技术标准和规范的统一方面可以发挥哪些作用?
政府在推动物联网技术标准和规范的统一方面可以发挥哪些作用?
66 50

相关产品

  • 物联网平台