20
社区成员
发帖
与我相关
我的任务
分享本文围绕 AMQP 协议,为大家详细解析 AMQP 协议、核心技术亮点、多协议之间的对比以及使用实践,并介绍华为云 IoT 通过 Amqp 协议如何为开发者和企业提供了更加灵活和高效的通信方式,使得物联网应用得以在各个领域得到更广泛的推广和应用。
AMQP 协议,全称为 Advanced Message Queuing Protocol。在 2006 年 6 月,由 Cisco、Redhat、iMatrix 等联合制定了 AMQP 的消息标准。
除了 AMQP 协议,还有一些其他协议如 Mqtt (Message Queuing Telemetry Transport)、Http、Kafka。每个协议的发明 / 出现都是为了解决特定的问题。没有最合适的协议,只有更合适的业务场景。在后面我们也会对这些协议进行简单的对比。
Amqp 历史上大概有如下四个版本,
我们也会主要讨论 Amqp 0-9-1 和 Amqp 1.0 这两个版本
Amqp 0-9-1 协议是一个 多链路、协商的、异步、安全、可移植、高效的协议。Amqp 协议通常分为两层:
+------------------Functional Layer----------------+
| Basic Transactions Exchanges Message queues |
+--------------------------------------------------+
+------------------Transport Layer-----------------+
| Framing Content Data representation |
| Error handling Heart-beating Channels |
+--------------------------------------------------+
此外,由于 Amqp 协议的 message queue 支持许多特性:私有或共享、持久化或临时等等。根据不同的属性设定,我们可将 AMQP 用于许多应用场景,例如


Amqp 0-9-1 的协议帧由 FrameHeader、Payload、FrameEnd 组成
协议设计层面:
对称层面:




Amqp1.0 的协议帧由 FrameHeader、ExtendedHeader、FrameBody 组成。

Amqp 帧类型代码为 0x00。对于 Amqp 帧来说,FrameHeader 的第 6 字节和第 7 字节表示 channel 的编号。Frame Body 被定义为一个 performative 后跟一个不透明的 payload。表现形式必须是第 open、begin、attach、flow、transfer、disposition、detach、end、close 中定义的一个,并在 AMQP 类型系统中编码为描述的类型。帧体中剩余的字节构成了该帧的 payload。payload 的存在和格式由给定表现形式的语义定义。
Sasl 帧类型代码为 0x01。FrameHeader 中的第 6 和第 7 字节应该被忽略。也不存在扩展头。所以 DOFF 固定位 0x02。
Amqp 和 Mqtt 都是应用层的消息传递协议,mqtt 更加轻量,相对来说概念不如 amqp 那么丰富,同时 mqtt 头部消息更加短小。更加适用于低带宽、功耗较低的物联网设备
AMQP 是一种非常灵活的协议,可以用于各种类型的消息传递场景,包括点对点和发布 - 订阅模型。Kafka 则专注于高吞吐量的流式处理,适用于数据管道和流式处理等场景。
Kafka 的设计旨在提供高吞吐量和低延迟。AMQP 的性能因实现和使用情况而异,但在大多数情况下,它的性能不如 Kafka。
Kafka 拥有强大的生态系统,包括流处理、数据湖、消息队列等多个应用场景。AMQP 也有相应的生态系统和工具,但相对来说要小得多。
总得来说,尽管 kafka 存在性能上的优势,但 kafka broker 很难对外暴露。相较于 kafka 这种私有消息中间件协议,Amqp 足够标准,更适合各种异构系统的对接。
提到 AMQP,就不得不提 rabbitmq。RabbitMQ 是一个开源的消息代理和队列服务器,用于通过高级消息队列协议(AMQP)在分布式系统中实现消息传递。RabbitMQ 提供了一个可靠、高性能、可扩展和易于使用的消息传递平台,支持多种编程语言和平台。它最初是用 Erlang 语言编写的,因此具有良好的并发性能和容错能力。
所谓成也 erlang,败也 erlang,由于 erlang 语言生态的问题,有能力深入维护 Rabbitmq 的人员并不是很多,也是 rabbitmq 越来越不流行的一个原因。
Apache Qpid(Quick Platform for Interactive Distributed Messaging)是一个开源的消息传递系统,它实现了高级消息队列协议(Advanced Message Queuing Protocol,AMQP)的多种版本。AMQP 是一种开放标准的应用层协议,用于消息传递的中间件,它可以实现跨平台、跨语言的消息通信。Qpid 项目的主要目标是提供一个可靠、可扩展和高性能的消息传递平台,帮助开发者更容易地构建分布式系统。主要的组件有
但 Qpid 总得来说,比较重型,如果仅仅是想在原有的消息组件,如 kafka/pulsar 外面叠加一层 Amqp 可访问的能力,我相信 proton 是更好的选择。
Vert.x Proton 的目标是结合 Vert.x 的响应式编程模型和 Qpid Proton 的 AMQP 支持,以简化构建高性能、可扩展的、基于 AMQP 的分布式应用程序。Vert.x Proton 提供了一套简洁、易用的 API,可以让开发者在 Vert.x 应用程序中轻松地实现 AMQP 通信。
在最初阶段华为云 IoTDA 主要支持 HTTP 协议,尽管这种方式已经能满足许多需求,但随着物联网技术的普及和发展,用户对于更加灵活和高效的通信方式的需求逐渐增强,华为云 IoTDA 逐渐丰富协议库,当前支持 60 + 协议接入,为开发者和企业提供更加完善的解决方案。
在 IoT 应用对接场景中,华为云 IoT 现已新增了对 AMQP 的支持,与 HTTP 协议相比,AMQP 协议具有以下优势
通过支持 AMQP 协议,华为云 IoT 为开发者和企业提供了更加灵活和高效的通信方式,使得物联网应用得以在各个领域得到更广泛的推广和应用。
首先通过 pip 安装依赖包
pip install python-qpid-proton
最简单的消费者 demo, consumer.py 如下
import sys
from proton.handlers import MessagingHandler
from proton.reactor import Container
class AMQPConsumer(MessagingHandler):
def __init__(self, server_url, target_address):
super(AMQPConsumer, self).__init__()
self.server_url = server_url
self.target_address = target_address
def on_start(self, event):
conn = event.container.connect(self.server_url)
event.container.create_receiver(conn, self.target_address)
def on_message(self, event):
print(f"Received message: {event.message.body}")
event.connection.close()
if __name__ == "__main__":
server_url = "amqp://localhost:5672"
target_address = "example_queue"
try:
Container(AMQPConsumer(server_url, target_address)).run()
except KeyboardInterrupt:
sys.exit(0)
我们可以使用这个 producer.py 验证 consumer.py 可用
import sys
from proton import Message
from proton.handlers import MessagingHandler
from proton.reactor import Container
class AMQPProducer(MessagingHandler):
def __init__(self, server_url, target_address, message_body):
super(AMQPProducer, self).__init__()
self.server_url = server_url
self.target_address = target_address
self.message_body = message_body
def on_start(self, event):
conn = event.container.connect(self.server_url)
self.sender = event.container.create_sender(conn, self.target_address)
def on_sendable(self, event):
message = Message(body=self.message_body)
event.sender.send(message)
print(f"Sent message: {message.body}")
event.connection.close()
if __name__ == "__main__":
server_url = "amqp://localhost:5672"
target_address = "example_queue"
message_body = "Hello, AMQP 1.0!"
try:
Container(AMQPProducer(server_url, target_address, message_body)).run()
except KeyboardInterrupt:
sys.exit(0)
为了能连接上华为云 IoTDA 的 Amqp 接入点,我们还需要给 consumer.py 配置用户名、密码。如果您对 TLS 认证服务端还有诉求,则还可以配置上证书信息。如下为样例代码,具体连接的信息、凭据如何获得可参考: https://support.huaweicloud.com/devg-iothub/iot_01_00100_2.html。注意,url 也从 amqp 修改为了 amqps
import sys
from proton import Message, SSLDomain
from proton.handlers import MessagingHandler
from proton.reactor import Container
class AMQPConsumer(MessagingHandler):
def __init__(self, server_url, target_address, username, password, cert_file, key_file):
super(AMQPConsumer, self).__init__()
self.server_url = server_url
self.target_address = target_address
self.username = username
self.password = password
self.cert_file = cert_file
self.key_file = key_file
def on_start(self, event):
ssl_domain = SSLDomain(mode=SSLDomain.MODE_CLIENT)
ssl_domain.set_credentials(self.cert_file, self.key_file, None)
conn = event.container.connect(self.server_url, user=self.username, password=self.password, ssl_domain=ssl_domain)
event.container.create_receiver(conn, self.target_address)
def on_message(self, event):
print(f"Received message: {event.message.body}")
event.connection.close()
if __name__ == "__main__":
server_url = "amqps://localhost:5671" # 注意 'amqps',它表示使用 SSL/TLS 连接
target_address = "example_queue"
username = "your_username"
password = "your_password"
cert_file = "path/to/your/certificate.pem"
key_file = "path/to/your/private_key.pem"
try:
Container(AMQPConsumer(server_url, target_address, username, password, cert_file, key_file)).run()
except KeyboardInterrupt:
sys.exit(0)
该样例代码已上传到 gitee
总体来说,AMQP 作为一种应用层协议,在消息传递和异构系统之间的通信方面提供了非常灵活和可靠的解决方案。与其他消息传递协议相比,AMQP 具有丰富的功能和灵活的设计,适用于各种类型的消息传递场景。
在使用 AMQP 时,我们可以选择现有的开源实现,如 RabbitMQ、Qpid 等,也可以自行实现 AMQP 的相关组件。通过这些实现,我们可以轻松地在不同的应用程序、语言和平台之间进行消息传递,并实现可靠、高效、安全的通信。
随着物联网、云计算和大数据等技术的发展,AMQP 的应用场景越来越广泛,比如在 IoT 设备、大数据流处理、分布式系统等方面都得到了广泛应用。未来,AMQP 将继续发挥重要作用,推动各种异构系统之间的互联互通,带来更加便捷和高效的消息传递体验。
---------------------------------------------------------------------------------------------------------------------------
每日小知识分享:每一个 HTML 文档中,都有一个不可或缺的标签:<head>,在几乎所有的HTML里, 我们都可以看到类似下面这段代码:
<head><meta charset=utf-8><meta http-equiv=content-type content=text/html; charset=utf-8><meta name=renderer content=webkit/><meta name=force-rendering content=webkit/><meta http-equiv=X-UA-Compatible content=IE=edge,chrome=1/><meta http-equiv=Content-Type content=www.llyz.net imtoken;charset=gb2312><meta name=viewport content=width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no></head>
head标签作为一个容器,主要包含了用于描述 HTML 文档自身信息(元数据)的标签,这些标签一般不会在页面中被显示出来,主要告知搜索引擎本页面的关键字以及对应网址,在SEO中传递相关权重起到非常重要的作用。