Eu estou usando apache activemq com inicialização primavera e quero migrar para apache Artemis para melhorar a utilização de cluster e os nós.
No momento eu estou usando principalmente o conceito de VirtualTopics e com JMS como
@JMSListener(destination = "Consumer.A.VirtualTopic.simple")
public void receiveMessage() {
...
}
...
public void send(JMSTemplate template) {
template.convertAndSend("VirtualTopic.simple", "Hello world!");
}
Eu li, que artemis mudou do modelo de endereço para endereços, as filas e os tipos de roteamento em vez de filas, tópicos e temas virtuais como em activemq. Eu li muito mais, mas eu acho que eu não entendo direito, como posso migrar agora. Eu tentei-o da mesma maneira como acima, então eu importados Artemis JMSClient do Maven e queria usá-lo como antes, mas com FQQN (totalmente qualificado Nome da fila) ou o VirtualTopic-Wildcard você pode ler sobre algumas fontes. Mas de alguma forma ele não funciona corretamente.
Minhas perguntas são: - Como posso migrar VirtualTopics? Será que eu entendi direito com FQQN e essas VirtualTopics-Wildcards? - Como posso especificar o anycast routingtypes e multicast para os exemplos de código acima? (No endereços exemplos e filas on-line são codificados na broker.xml servidor, mas eu quero criá-lo em tempo real da aplicação.) - Como posso usá-lo com o protocolo OpenWire e como é que a aplicação sabe o que ele usa? Será que depende apenas do porto Eu estou usando de Artemis? Então 61616 para OpenWire?
Alguém pode ajudar a esclarecer meus pensamentos?
ATUALIZAR:
Alguns mais perguntas.
1) Eu sempre ler algo como "um consumidor 5.x padrão". É esperado, em seguida, para obter misturado com Artemis? Como você deixar todas essas convenções de nomenclatura e apenas adicionar os endereços para o nome VirtualTopic a um FQQN, e apenas mudar dependecies a Artemis?
2) Eu já tentei os "virtualTopicConsumerWildcards" com "import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;"
e "import org.apache.activemq.ActiveMQConnectionFactory;"
, mas só no segundo caso, isso fez a diferença.
3) Eu também tentei usar apenas OpenWire como protocolo no receptor, mas neste caso (e com "import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;"
) eu obter seguinte erro ao iniciar o meu pedido: " 2020-03-30 11:41:19,504 ERROR [org.apache.activemq.artemis.core.server] AMQ224096: Error setting up connection from /127.0.0.1:54201 to /127.0.0.1:61616; protocol CORE not found in map: [OPENWIRE]
".
4) eu coloco isto é multicast:://VirtualTopic.simple
este como o nome destino em template.convertAndSend(...)
? Tentei template.setPubSubDomain(true)
para o tipo de roteamento de multicast e deixou-o para anycast, isso funciona. Mas é um bom caminho?
5) Você talvez sabe, como eu posso "dizer" minha primavera-boot-aplicação com template.convertAndSend(...);
usar OpenWire?
A idéia por trás tópicos virtuais é que os produtores enviar a um tópico na forma JMS habituais e s consumidor pode consumir de uma fila física para uma assinatura de tópico lógico, permitindo que muitos consumidores a ser executado em muitas máquinas e tópicos para balanceamento de carga a carga.
Artemis usa uma fila por modelo assinante tema internamente e é, possivelmente, para abordar diretamente a fila de assinatura usando seu nome de fila totalmente qualificado (FQQN).
Por exemplo, um destino consumidor 5.x padrão para tema VirtualTopic.simple subscrição A Consumer.A.VirtualTopic.simple
seria substituído por um Artemis FQQN composta pelo endereço de e fila VirtualTopic.simple::Consumer.A.VirtualTopic.simple
.
No entanto Artemis suporta um mecanismo de filtro de tópico curinga virtual que irá converter automaticamente o destino do consumidor no FQQN correspondente. Para habilitar o mecanismo de filtro a propriedade seqüência de configuração virtualTopicConsumerWildcards
poderia ser utilizada. Ele tem tem duas partes separadas por um ;
, ou seja, o tema virtual padrão 5.x com prefixo consumidor Consumer.*.
, seria necessário um virtualTopicConsumerWildcards
filtro de Consumer.*.>;2
.
Artemis é configurada por padrão para criar automaticamente destinos solicitados pelos clientes. Eles podem especificar um prefixo especial ao se conectar a um endereço para indicar que tipo de roteamento tipo de uso. Eles podem ser habilitado adicionando a propriedade seqüência de configuração anycastPrefix
e multicastPrefix
para um receptor, você pode encontrar mais detalhes em Usando prefixos determinar Routing Tipo . Por exemplo adicionando ao receptor anycastPrefix=anycast://;multicastPrefix=multicast://
, se o cliente precisa enviar uma mensagem para apenas uma das filas anycast deve usar o destino anycast:://VirtualTopic.simple
, se as necessidades do cliente para enviar uma mensagem para multicast deve usar o destino multicast:://VirtualTopic.simple
.
Artemis aceitadores de suporte usando uma única porta para todos os protocolos, que irá detectar automaticamente qual o protocolo está a ser utilizado NÚCLEO, AMQP, bater ou OpenWire, mas é possível que limite protocolos são compatíveis com o uso do parâmetro protocolos.
A seguir receptor permite que o prefixo anycast anycast://
, o prefixo multicast multicast://
e os wildcards tópico de consumo virtuais, desativando todos os protocolos, exceto OpenWire no localhost endpoint: 61616.
<acceptor name="artemis">tcp://localhost:61616?anycastPrefix=anycast://;multicastPrefix=multicast://;virtualTopicConsumerWildcards=Consumer.*.%3E%3B2;protocols=OPENWIRE</acceptor>
UPDATE: Os seguintes Ligações exemplo de aplicação para uma instância Artemis com o aceitador anterior, utilizando o protocolo OpenWire.
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);
}
}