将现有 Java 消息服务 (JMS) 2.0 应用程序从 Apache ActiveMQ 迁移到 Azure 服务总线

本文介绍了如何修改与 JMS 代理进行交互的现有 Java 消息服务 (JMS) 2.0 应用程序,以使其改为与 Azure 服务总线进行交互。 具体而言,本文介绍了如何从 Apache ActiveMQ 或 Amazon MQ 进行迁移。

Azure 服务总线支持 Java 2 Platform Enterprise Edition 和 Spring 工作负载,此类工作负载使用基于高级消息排队协议 (AMQP) 的 JMS 2.0 API。

开始之前

Azure 服务总线与 Apache ActiveMQ 之间的差异

Azure 服务总线和 Apache ActiveMQ 都是消息代理,充当 JMS 提供程序,客户端应用程序向其发送消息并从中接收消息。 它们都使用队列实现点到点语义,并使用主题和订阅实现发布-订阅语义。

尽管如此,这两者之间还是存在一些差异,如下表所示:

类别 ActiveMQ Azure 服务总线
应用程序分层 群集单体架构 两层
(网关 + 后端)
协议支持
  • AMQP
  • STOMP
  • OpenWire
AMQP
预配模式
  • 基础结构即服务 (IaaS),本地
  • Amazon MQ(托管平台即服务)
托管平台即服务 (PaaS)
消息大小 允许客户进行配置 100 MB(高级层)
高可用性 由客户管理 由平台管理
灾难恢复 由客户管理 由平台管理

当前支持的和不支持的功能

下表列出了 Azure 服务总线当前支持的 Java 消息服务 (JMS) 功能。 它还展示了不支持的功能。

功能 API 状态
队列
  • JMSContext.createQueue(String queueName)
支持
主题
  • JMSContext.createTopic(String topicName)
支持
临时队列
  • JMSContext.createTemporaryQueue()
支持
临时主题
  • JMSContext.createTemporaryTopic()
支持
消息生成者/
JMSProducer
  • JMSContext.createProducer()
支持
队列浏览器
  • JMSContext.createBrowser(Queue queue)
  • JMSContext.createBrowser(Queue queue, String messageSelector)
支持
消息使用者/
JMSConsumer
  • JMSContext.createConsumer(Destination destination)
  • JMSContext.createConsumer(Destination destination, String messageSelector)
  • JMSContext.createConsumer(Destination destination, String messageSelector, boolean noLocal)

目前不支持 noLocal
支持
共享持久订阅
  • JMSContext.createSharedDurableConsumer(Topic topic, String name)
  • JMSContext.createSharedDurableConsumer(Topic topic, String name, String messageSelector)
支持
非共享持久订阅
  • JMSContext.createDurableConsumer(Topic topic, String name)
  • createDurableConsumer(Topic topic, String name, String messageSelector, boolean noLocal)

目前不支持 noLocal,应将其设置为 false
支持
共享非持久订阅
  • JMSContext.createSharedConsumer(Topic topic, String sharedSubscriptionName)
  • JMSContext.createSharedConsumer(Topic topic, String sharedSubscriptionName, String messageSelector)
支持
非共享非持久订阅
  • JMSContext.createConsumer(Destination destination)
  • JMSContext.createConsumer(Destination destination, String messageSelector)
  • JMSContext.createConsumer(Destination destination, String messageSelector, boolean noLocal)

目前不支持 noLocal,应将其设置为 false
支持
消息选择器 取决于创建的使用者 支持
交付延迟(计划的消息)
  • JMSProducer.setDeliveryDelay(long deliveryDelay)
支持
创建的消息
  • JMSContext.createMessage()
  • JMSContext.createBytesMessage()
  • JMSContext.createMapMessage()
  • JMSContext.createObjectMessage(Serializable object)
  • JMSContext.createStreamMessage()
  • JMSContext.createTextMessage()
  • JMSContext.createTextMessage(String text)
支持
跨实体事务
  • Connection.createSession(true, Session.SESSION_TRANSACTED)
支持
分布式事务 不支持

注意事项

Azure 服务总线的双层特性提供了各种业务连续性功能(高可用性和灾难恢复)。 但是,在使用 JMS 功能时,有一些注意事项。

服务升级

在服务总线升级和重启时,会删除临时队列或主题。 如果你的应用程序对临时队列或主题的数据丢失敏感,请不要使用临时队列或主题。 请改用持久性队列、主题和订阅。

数据迁移

在迁移和修改客户端应用程序来与 Azure 服务总线进行交互的过程中,ActiveMQ 中保存的数据不会迁移到服务总线。 你可能需要使用自定义应用程序来清空 ActiveMQ 队列、主题和订阅,然后将消息重播到服务总线的队列、主题和订阅。

身份验证和授权

Microsoft Entra ID 支持的 Azure 基于角色的访问控制 (Azure RBAC) 是服务总线的首选身份验证机制。 若要启用基于角色的访问控制,请按照 Azure 服务总线 JMS 2.0 开发人员指南中的步骤操作。

预迁移

版本检查

编写 JMS 应用程序时,可以使用以下组件和版本:

组件 版本
Java 消息服务 (JMS) API 1.1 或更高版本
AMQP 协议 1.0

确保 AMQP 端口已打开

服务总线支持通过 AMQP 协议进行通信。 为此,请启用通过端口 5671 (AMQP) 和 443 (TCP) 进行的通信。 根据客户端应用程序的托管位置,你可能需要一个支持票证来允许通过这些端口进行通信。

重要

服务总线仅支持 AMQP 1.0 协议。

设置企业配置

服务总线可实现各种企业安全性和高可用性功能。 有关详情,请参阅:

监视、警报和跟踪

对于每个服务总线命名空间,请将指标发布到 Azure Monitor。 你可以使用这些指标对分配给命名空间的资源发出警报,以及对其进行动态缩放。

若要详细了解各种指标以及如何基于这些指标设置警报,请参阅 Azure Monitor 中的服务总线指标。 你还可以进一步了解数据操作的客户端跟踪管理操作的操作/诊断日志记录

指标 - New Relic

你可以将 ActiveMQ 中的指标与映射到的 Azure 服务总线中的指标进行关联。 请参阅来自 New Relic 网站的以下内容:

注意

目前,New Relic 没有与 ActiveMQ 直接无缝集成,但它们具有可用于 Amazon MQ 的指标。 由于 Amazon MQ 派生自 ActiveMQ,因此下表将 New Relic 指标从 Amazon MQ 映射到 Azure 服务总线。

指标分组 Amazon MQ/ActiveMQ 指标 Azure 服务总线指标
代理 CpuUtilization CPUXNS
代理 MemoryUsage WSXNS
代理 CurrentConnectionsCount activeConnections
代理 EstablishedConnectionsCount activeConnections + connectionsClosed
代理 InactiveDurableTopicSubscribersCount 使用订阅指标
代理 TotalMessageCount 使用队列/主题/订阅级别 activeMessages
队列/主题 EnqueueCount incomingMessages
队列/主题 DequeueCount outgoingMessages
队列 QueueSize sizeBytes

迁移

若要迁移现有的 JMS 2.0 应用程序来与服务总线交互,请按照以下几部分中的步骤进行操作。

从 ActiveMQ 中导出拓扑并在服务总线中创建实体(可选)

若要确保客户端应用程序可以无缝连接到服务总线,请将拓扑(包括队列、主题和订阅)从 Apache ActiveMQ 迁移到服务总线。

注意

对于 JMS 应用程序,请以运行时操作的方式创建队列、主题和订阅。 大多数 JMS 提供程序(消息代理)提供了在运行时创建它们的功能。 这就是可将此导出步骤视为可选步骤的原因。 若要确保应用程序具有在运行时创建拓扑的权限,请使用具有 SAS Manage 权限的连接字符串。

要执行此操作:

  1. 使用 ActiveMQ 命令行工具导出拓扑。
  2. 使用 Azure 资源管理器模板重新创建相同的拓扑。
  3. 运行 Azure 资源管理器模板。

导入用于服务总线 JMS 实现的 maven 依赖项

若要确保与服务总线的无缝连接,请将 azure-servicebus-jms 包作为依赖项添加到 Maven pom.xml 文件中,如下所示:

<dependencies>
...
    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-servicebus-jms</artifactId>
    </dependency>
...
</dependencies>

应用程序服务器配置更改

此部分自定义为承载着你的客户端应用程序(连接到 ActiveMQ)的应用程序服务器。

Spring 应用程序

更新 application.properties 文件

如果你使用 Spring 引导应用程序连接到 ActiveMQ,则需要从 application.properties 文件中删除特定于 ActiveMQ 的属性。

spring.activemq.broker-url=<ACTIVEMQ BROKER URL>
spring.activemq.user=<ACTIVEMQ USERNAME>
spring.activemq.password=<ACTIVEMQ PASSWORD>

然后,将特定于服务总线的属性添加到 application.properties 文件中。

azure.servicebus.connection-string=Endpoint=myEndpoint;SharedAccessKeyName=mySharedAccessKeyName;SharedAccessKey=mySharedAccessKey
ActiveMQConnectionFactory 替换为 ServiceBusJmsConnectionFactory

下一步是将 ActiveMQConnectionFactory 的实例替换为 ServiceBusJmsConnectionFactory

注意

实际代码更改取决于应用程序以及管理依赖项的方式,但你可以遵照以下示例来更改相关内容。

以前,你可能已经实例化了 ActiveMQConnectionFactory 的一个对象,如下所示:


String BROKER_URL = "<URL of the hosted ActiveMQ broker>";
ConnectionFactory factory = new ActiveMQConnectionFactory(BROKER_URL);

Connection connection = factory.createConnection();
connection.start();

现在,你要更改此代码以实例化 ServiceBusJmsConnectionFactory 的一个对象,如下所示:


ServiceBusJmsConnectionFactorySettings settings = new ServiceBusJmsConnectionFactorySettings();
String SERVICE_BUS_CONNECTION_STRING = "<Service Bus Connection string>";

ConnectionFactory factory = new ServiceBusJmsConnectionFactory(SERVICE_BUS_CONNECTION_STRING, settings);

Connection connection = factory.createConnection();
connection.start();

迁移后

现在,你已修改了应用程序,开始从服务总线发送和接收消息,因此应该验证它是否按预期方式工作。 完成此操作后,你可以进一步将应用程序堆栈优化和现代化。

后续步骤

若要详细了解服务总线消息传送和 JMS,请参阅: