gpt4 book ai didi

java - Spring Boot将apache activemq迁移到artemis

转载 作者:行者123 更新时间:2023-12-02 00:59:15 27 4
gpt4 key购买 nike

我正在使用 apache activemq 和 spring boot,我想迁移到 apache artemis 以提高集群和节点的使用率。

目前我主要使用VirtualTopics的概念以及像JMS这样的

@JMSListener(destination = "Consumer.A.VirtualTopic.simple")
public void receiveMessage() {
...
}

...

public void send(JMSTemplate template) {
template.convertAndSend("VirtualTopic.simple", "Hello world!");
}

我读到,artemis 将其地址模型更改为地址、队列和路由类型,而不是像 activemq 中的队列、主题和虚拟主题。我已经阅读了很多内容,但我认为我现在不明白如何迁移。我按照上面的方法尝试了,所以我导入了 Artemis JMSClient来自 Maven 并想像以前一样使用它,但是使用 FQQN(完全限定队列名称)VirtualTopic-Wildcard 您可以阅读某些来源。但不知怎的,它不能正常工作。

我的问题是:- 如何迁移 VirtualTopics?我对 FQQN 和那些 VirtualTopics-Wildcards 的理解正确吗?- 如何为上面的代码示例指定路由类型任播和多播? (在在线示例中,地址和队列被硬编码在服务器broker.xml中,但我想在应用程序运行时创建它。)- 我如何将它与 openwire 协议(protocol)一起使用以及应用程序如何知道它使用什么?它仅取决于我使用的 artemis 端口吗?那么 61616 适合 openwire 吗?

谁能帮我理清思路吗?

更新:

一些进一步的问题。

1) 我总是读到“默认的 5.x 消费者”之类的内容。那么它会与阿尔忒弥斯混合吗?就像您保留所有这些命名约定,只需将 VirtualTopic 名称的地址添加到 FQQN,然后将依赖项更改为 artemis?

2)我已经尝试过“virtualTopicConsumerWildcards”与“import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;”“import org.apache.activemq .ActiveMQConnectionFactory;",但仅在第二种情况下才产生影响。

3) 我还尝试仅使用 OpenWire 作为接受器中的协议(protocol),但在本例中(并且使用 "import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;")启动应用程序时出现以下错误:“2020-03-30 11:41:19,504 ERROR [org.apache.activemq.artemis.core.server] AMQ224096:从/127.0.0.1:54201 设置连接时出错到/127.0.0.1:61616;在 map 中找不到协议(protocol)核心:[OPENWIRE]”。

4) 我是否将 multicast:://VirtualTopic.simple 将此作为 template.convertAndSend(...) 中的目标名称?我尝试了 template.setPubSubDomain(true) 作为多播路由类型,并将其保留为任播,这有效。但这是个好方法吗?

5) 你可能知道,我如何使用 template.convertAndSend(...); “告诉”我的 spring-boot-application 使用 Openwire?

更新2:共享持久订阅

@JmsListener(destination = "VirtualTopic.test", id = "c1", subscription = "Consumer.A.VirtualTopic.test", containerFactory = "queueConnectionFactory")
public void receive1(String m) {

}

@JmsListener(destination = "VirtualTopic.test", id = "c2", subscription = "Consumer.B.VirtualTopic.test", containerFactory = "queueConnectionFactory")
public void receive2(String m) {

}
<小时/>
@Bean
public DefaultJmsListenerContainerFactory queueConnectionFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setClientId("brokerClientId");
factory.setSubscriptionDurable(true);
factory.setSubscriptionShared(true);
return factory;
}

错误:

2020-04-17 11:23:44.485  WARN 7900 --- [enerContainer-3] o.s.j.l.DefaultMessageListenerContainer  : Setup of JMS message listener invoker failed for destination 'VirtualTopic.test' - trying to recover. Cause: org.apache.activemq.ActiveMQSession.createSharedDurableConsumer(Ljavax/jms/Topic;Ljava/lang/String;Ljava/lang/String;)Ljavax/jms/MessageConsumer; 
2020-04-17 11:23:44.514 ERROR 7900 --- [enerContainer-3] o.s.j.l.DefaultMessageListenerContainer : Could not refresh JMS Connection for destination 'VirtualTopic.test' - retrying using FixedBackOff{interval=5000, currentAttempts=0, maxAttempts=unlimited}. Cause: Broker: d1 - Client: brokerClientId already connected from /127.0.0.1:59979

我在这里做错了什么?

最佳答案

虚拟主题背后的想法是,生产者以通常的 JMS 方式发送到主题,而消费者可以从物理队列中消费逻辑主题订阅,从而允许许多消费者在许多机器和线程上运行,以平衡主题的负载。负载。

Artemis 在内部使用每个主题订阅者模型的队列,并且可能使用其 Fully Qualified Queue name 直接寻址订阅队列。 (FQQN)。

例如,主题 VirtualTopic.simple 订阅的默认 5.x 消费者目标 Consumer.A.VirtualTopic.simple 将替换为由地址和队列组成的 Artemis FQQN VirtualTopic.simple::Consumer.A.VirtualTopic.simple.

但是 Artemis 支持 virtual topic wildcard filter mechanism它将自动将消费目的地转换为相应的 FQQN。要启用过滤机制,配置字符串属性可以使用virtualTopicConsumerWildcards。它有两个部分,由 ; 分隔,即消费者前缀为 Consumer.*. 的默认 5.x 虚拟主题需要 virtualTopicConsumerWildcards Consumer.*.>;2.

的 code> 过滤器

Artemis 默认配置为自动创建客户端请求的目的地。它们可以在连接到地址时指定特殊前缀,以指示要使用哪种路由类型。可以通过将配置字符串属性 anycastPrefixmulticastPrefix 添加到接受器来启用它们,您可以在 Using Prefixes to Determine Routing Type 找到更多详细信息。 。例如,添加到接受器 anycastPrefix=anycast://;multicastPrefix=multicast://,如果客户端需要仅向其中一个 ANYCAST 队列发送消息,则应使用目标 anycast:://VirtualTopic.simple,如果客户端需要向 MULTICAST 发送消息,应使用目标multicast:://VirtualTopic.simple

阿耳忒弥斯 acceptors支持对所有协议(protocol)使用单个端口,它们会自动检测正在使用哪个协议(protocol) CORE、AMQP、STOMP 或 OPENWIRE,但可以使用协议(protocol)参数来限制支持哪些协议(protocol)。

以下接受器启用任播前缀 anycast://、多播前缀 multicast:// 和虚拟主题消费者通配符,禁用除 OPENWIRE 之外的所有协议(protocol)端点本地主机:61616。

<acceptor name="artemis">tcp://localhost:61616?anycastPrefix=anycast://;multicastPrefix=multicast://;virtualTopicConsumerWildcards=Consumer.*.%3E%3B2;protocols=OPENWIRE</acceptor>

更新:以下示例应用程序使用 OpenWire 协议(protocol)连接到具有先前接受器的 Artemis 实例。

import org.apache.activemq.ActiveMQConnectionFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;

@SpringBootApplication
@EnableJms
public class Application {

private final String BROKER_URL = "tcp://localhost:61616";
private final String BROKER_USERNAME = "admin";
private final String BROKER_PASSWORD = "admin";

public static void main(String[] args) throws Exception {
final ConfigurableApplicationContext context = SpringApplication.run(Application.class);
System.out.println("********************* Sending message...");

JmsTemplate jmsTemplate = context.getBean("jmsTemplate", JmsTemplate.class);
JmsTemplate jmsTemplateAnycast = context.getBean("jmsTemplateAnycast", JmsTemplate.class);
JmsTemplate jmsTemplateMulticast = context.getBean("jmsTemplateMulticast", JmsTemplate.class);

jmsTemplateAnycast.convertAndSend("VirtualTopic.simple", "Hello world anycast!");
jmsTemplate.convertAndSend("anycast://VirtualTopic.simple", "Hello world anycast using prefix!");
jmsTemplateMulticast.convertAndSend("VirtualTopic.simple", "Hello world multicast!");
jmsTemplate.convertAndSend("multicast://VirtualTopic.simple", "Hello world multicast using prefix!");

System.out.print("Press any key to close the context");
System.in.read();

context.close();
}

@Bean
public ActiveMQConnectionFactory connectionFactory(){
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
connectionFactory.setBrokerURL(BROKER_URL);
connectionFactory.setUserName(BROKER_USERNAME);
connectionFactory.setPassword(BROKER_PASSWORD);
return connectionFactory;
}

@Bean
public JmsTemplate jmsTemplate(){
JmsTemplate template = new JmsTemplate();
template.setConnectionFactory(connectionFactory());
return template;
}

@Bean
public JmsTemplate jmsTemplateAnycast(){
JmsTemplate template = new JmsTemplate();
template.setPubSubDomain(false);
template.setConnectionFactory(connectionFactory());
return template;
}

@Bean
public JmsTemplate jmsTemplateMulticast(){
JmsTemplate template = new JmsTemplate();
template.setPubSubDomain(true);
template.setConnectionFactory(connectionFactory());
return template;
}

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setConcurrency("1-1");
return factory;
}

@JmsListener(destination = "Consumer.A.VirtualTopic.simple")
public void receiveMessageFromA(String message) {
System.out.println("*********************** MESSAGE RECEIVED FROM A: " + message);
}

@JmsListener(destination = "Consumer.B.VirtualTopic.simple")
public void receiveMessageFromB(String message) {
System.out.println("*********************** MESSAGE RECEIVED FROM B: " + message);
}

@JmsListener(destination = "VirtualTopic.simple")
public void receiveMessageFromTopic(String message) {
System.out.println("*********************** MESSAGE RECEIVED FROM TOPIC: " + message);
}
}

关于java - Spring Boot将apache activemq迁移到artemis,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60919531/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com