Após criar recursos do ApsaraMQ for RocketMQ, como um tópico e um grupo de consumidores, você pode integrar a mensageria à sua aplicação Java. Este guia mostra como adicionar a dependência do SDK para Java 5.x, conectar-se à sua instância, enviar mensagens normais e consumi-las com um consumidor push ou um consumidor simples.
Antes de começar
Certifique-se de ter:
Recursos criados no ApsaraMQ for RocketMQ, incluindo um tópico e um grupo de consumidores (Etapa 2 desta série)
Uma IDE Java, como o IntelliJ IDEA ou o Eclipse (os exemplos usam o IntelliJ IDEA Ultimate)
Adicione a dependência do SDK
Crie um projeto Java na sua IDE.
-
Adicione a seguinte dependência ao
pom.xml:<dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-client-java</artifactId> <version>5.0.7</version> </dependency>
**FAQ: E se eu receber o erro ClassNotFoundException: com.google.protobuf.GeneratedMessageV3 após adicionar a dependência rocketmq-client-java?**
Esse erro geralmente ocorre devido a um conflito de dependências, em que uma dependência mais antiga no seu projeto, como o rocketmq-spring-boot-starter, interfere ao carregar as classes do Protobuf.
Para resolver esse problema:
Certifique-se de que o seu projeto inclua a dependência
protobuf-javacorreta ou isole SDKs de versões diferentes em módulos separados para evitar o conflito.Caso não seja possível dividir os SDKs em módulos separados, adicione explicitamente as dependências
rocketmq-protoeprotobuf-java.
O SDK rocketmq-client-java usado pelo consumidor simples já inclui uma versão shaded do Protobuf (org.apache.rocketmq.shaded.com.google.protobuf). Na maioria dos casos, não é necessário adicionar com.google.protobuf:protobuf-java separadamente.
Reúna os parâmetros de conexão
Colete os seguintes valores no console do ApsaraMQ for RocketMQ antes de escrever qualquer código:
|
Parâmetro |
Exemplo |
Onde encontrar |
|
|
|
Página Instance Details > aba Endpoints. Use o endpoint de VPC ao acessar a instância a partir de uma instância do Elastic Compute Service (ECS) na mesma VPC, ou o endpoint público para acesso pela Internet. Consulte Obter o endpoint de uma instância. |
|
|
|
O tópico criado para enviar e receber mensagens. Crie-o previamente. Veja Criar um tópico. |
|
|
|
O grupo de consumidores criado. Crie-o previamente. Confira Criar um grupo de consumidores. |
|
|
|
O ID da sua instância do ApsaraMQ for RocketMQ. Necessário apenas para instâncias serverless acessadas pela Internet. |
|
Nome de usuário da instância |
|
Página Access Control > aba Intelligent Authentication. Veja Obter o nome de usuário e a senha de uma instância. |
|
Senha da instância |
|
Mesmo local do nome de usuário. |
Quando as credenciais são necessárias
A necessidade de fornecer nome de usuário, senha e namespace depende do seu método de acesso:
|
Método de acesso |
Nome de usuário e senha |
Namespace (ID da instância) |
|
VPC (instância padrão) |
Não é necessário. O broker obtém as credenciais automaticamente a partir das informações da VPC. |
Não é necessário. |
|
VPC (instância serverless, isento de autenticação ativado) |
Não é necessário. |
Não é necessário. |
|
VPC (instância serverless, isento de autenticação desativado) |
É necessário. |
Não é necessário. |
|
Internet (instância padrão) |
É necessário. Ative primeiro o acesso à Internet na instância. |
Não é necessário. |
|
Internet (instância serverless) |
É necessário. |
É necessário. Defina via |
Envie mensagens
Crie um arquivo ProducerExample.java no seu projeto e execute-o:
import org.apache.rocketmq.client.apis.*;
import org.apache.rocketmq.client.apis.message.Message;
import org.apache.rocketmq.client.apis.producer.Producer;
import org.apache.rocketmq.client.apis.producer.SendReceipt;
public class ProducerExample {
public static void main(String[] args) throws ClientException {
// Instance endpoint. Use the VPC endpoint when accessing from an ECS instance in the same VPC; use the public endpoint for Internet access.
String endpoints = "<your-endpoint>";
// Topic (must be pre-created in the console)
String topic = "<your-topic>";
ClientServiceProvider provider = ClientServiceProvider.loadService();
ClientConfiguration clientConfiguration = ClientConfiguration.newBuilder()
.setEndpoints(endpoints)
// Uncomment for serverless instances accessed over the Internet:
// .setNamespace("<your-instance-id>")
// Uncomment for Internet access or serverless VPC without authentication-free:
// .setCredentialProvider(new StaticSessionCredentialsProvider("<instance-username>", "<instance-password>"))
.build();
Producer producer = provider.newProducerBuilder()
.setTopics(topic)
.setClientConfiguration(clientConfiguration)
.build();
Message message = provider.newMessageBuilder()
.setTopic(topic)
.setKeys("messageKey")
.setTag("messageTag")
.setBody("messageBody".getBytes())
.build();
try {
SendReceipt sendReceipt = producer.send(message);
System.out.println(sendReceipt.getMessageId());
} catch (ClientException e) {
e.printStackTrace();
}
}
}
Substitua os placeholders pelos seus valores:
|
Placeholder |
Descrição |
|
|
Endpoint da instância, por exemplo |
|
|
Nome do tópico, por exemplo |
|
|
ID da instância (apenas para acesso serverless pela Internet) |
|
|
Nome de usuário da instância (acesso pela Internet ou VPC serverless sem autenticação) |
|
|
Senha da instância (acesso pela Internet ou VPC serverless sem autenticação) |
O método .setTopics() durante a inicialização do produtor valida as configurações do tópico antecipadamente. Isso é opcional para mensagens normais (validadas dinamicamente no momento do envio), mas obrigatório para mensagens transacionais, a fim de evitar falhas na API de consulta.
Se falhar o envio de uma mensagem, ela não é gravada no servidor, logo, não é possível consultá-la pelo ID da mensagem no console posteriormente. No código da sua aplicação, capture a exceção (por exemplo, em SendCallback.onException), registre o conteúdo completo da mensagem no log e tente reenviá-la com base na sua lógica de negócios.
Receba mensagens
O ApsaraMQ for RocketMQ oferece dois tipos de consumidores:
|
Consumidor push |
Consumidor simples |
|
|
Como funciona |
O SDK entrega as mensagens a um callback (listener de mensagens). |
A aplicação puxa as mensagens e confirma (ack) explicitamente cada uma. |
|
Concorrência |
Gerenciada pelo SDK. |
Gerenciada pela aplicação. |
|
Flexibilidade |
Menor. O SDK encapsula o fluxo de consumo. |
Maior. Operações atômicas permitem criar fluxos de trabalho personalizados. |
|
Ideal para |
A maioria dos casos de uso em que é necessário processar mensagens recebidas. |
Cenários que exigem controle refinado sobre a busca, o processamento ou a confirmação. |
Comece com um consumidor push, a menos que seja necessário um controle personalizado sobre o fluxo de consumo.
Ao usar o rocketmq-spring-boot-starter ou o rocketmq-v5-client-spring-boot-starter para integrar o SDK ao Spring Boot, fique atento às seguintes limitações e diferenças de configuração:
A anotação
@RocketMQMessageListenerno rocketmq-spring-boot-starter suporta apenas o consumidor push. Caso precise de um consumidor simples, inicialize-o manualmente no código, pois a anotação não oferece esse suporte.No rocketmq-v5-client-spring-boot-starter, o consumidor simples e as alterações dinâmicas em sua duração de invisibilidade atualmente também requerem inicialização manual no código. Esses elementos não são injetados automaticamente por meio de anotações.
No arquivo de configuração do starter v5, use o parâmetro
endpointsem vez do parâmetroname-serverusado anteriormente.O parâmetro de namespace difere de acordo com o starter: com o rocketmq-v5-client-spring-boot-starter, configure
namespace; com o rocketmq-spring-boot-starter, configurenamespaceV2. Caso o arquivo de configuração YAML não suporte esse parâmetro, defina-o no código.
Consumidor push
Crie um arquivo PushConsumerExample.java e execute-o:
import org.apache.rocketmq.client.apis.*;
import org.apache.rocketmq.client.apis.consumer.ConsumeResult;
import org.apache.rocketmq.client.apis.consumer.FilterExpression;
import org.apache.rocketmq.client.apis.consumer.FilterExpressionType;
import org.apache.rocketmq.client.apis.consumer.PushConsumer;
import org.apache.rocketmq.shaded.org.slf4j.Logger;
import org.apache.rocketmq.shaded.org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Collections;
public class PushConsumerExample {
private static final Logger LOGGER = LoggerFactory.getLogger(PushConsumerExample.class);
private PushConsumerExample() {
}
public static void main(String[] args) throws ClientException, IOException, InterruptedException {
String endpoints = "<your-endpoint>";
String topic = "<your-topic>";
String consumerGroup = "<your-consumer-group>";
final ClientServiceProvider provider = ClientServiceProvider.loadService();
ClientConfiguration clientConfiguration = ClientConfiguration.newBuilder()
.setEndpoints(endpoints)
// Uncomment for serverless instances accessed over the Internet:
// .setNamespace("<your-instance-id>")
// Uncomment for Internet access or serverless VPC without authentication-free:
// .setCredentialProvider(new StaticSessionCredentialsProvider("<instance-username>", "<instance-password>"))
.build();
// Subscribe to all messages in the topic (tag = "*")
String tag = "*";
FilterExpression filterExpression = new FilterExpression(tag, FilterExpressionType.TAG);
PushConsumer pushConsumer = provider.newPushConsumerBuilder()
.setClientConfiguration(clientConfiguration)
.setConsumerGroup(consumerGroup)
.setSubscriptionExpressions(Collections.singletonMap(topic, filterExpression))
.setMessageListener(messageView -> {
System.out.println("Consume Message: " + messageView);
return ConsumeResult.SUCCESS;
})
.build();
// Keep the consumer running
Thread.sleep(Long.MAX_VALUE);
// To shut down the consumer gracefully, call:
// pushConsumer.close();
}
}
O consumidor push no SDK gRPC do ApsaraMQ for RocketMQ 5.x usa uma fila interna de buffer local. Mesmo com o consumo em thread única, o SDK faz a pré-busca de mensagens para esse buffer. Se a lógica de negócio demorar muito para processar cada mensagem, essa pré-busca pode causar tempos limite de espera locais e usar recursos desnecessariamente.
Para lógicas de negócio de longa duração, use um consumidor simples (modo pull). O consumidor simples permite controlar a quantidade exata de mensagens puxadas por vez. Além disso, puxe o próximo lote apenas após processar e confirmar o lote atual. Defina InvisibleDuration (o período durante o qual uma mensagem recebida permanece invisível para outros consumidores, de 10 segundos a 12 horas) para controlar o tempo limite de confirmação e estendê-lo dinamicamente, se necessário.
Consumidor simples
Crie um arquivo SimpleConsumerExample.java e execute-o:
import org.apache.rocketmq.client.apis.*;
import org.apache.rocketmq.client.apis.consumer.FilterExpression;
import org.apache.rocketmq.client.apis.consumer.FilterExpressionType;
import org.apache.rocketmq.client.apis.consumer.SimpleConsumer;
import org.apache.rocketmq.client.apis.message.MessageId;
import org.apache.rocketmq.client.apis.message.MessageView;
import org.apache.rocketmq.shaded.org.slf4j.Logger;
import org.apache.rocketmq.shaded.org.slf4j.LoggerFactory;
import java.io.IOException;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
public class SimpleConsumerExample {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleConsumerExample.class);
private SimpleConsumerExample() {
}
public static void main(String[] args) throws ClientException, IOException {
String endpoints = "<your-endpoint>";
String topic = "<your-topic>";
String consumerGroup = "<your-consumer-group>";
final ClientServiceProvider provider = ClientServiceProvider.loadService();
ClientConfiguration clientConfiguration = ClientConfiguration.newBuilder()
.setEndpoints(endpoints)
// Uncomment for serverless instances accessed over the Internet:
// .setNamespace("<your-instance-id>")
// Uncomment for Internet access or serverless VPC without authentication-free:
// .setCredentialProvider(new StaticSessionCredentialsProvider("<instance-username>", "<instance-password>"))
.build();
// Long polling timeout
Duration awaitDuration = Duration.ofSeconds(10);
// Subscribe to all messages in the topic (tag = "*")
String tag = "*";
FilterExpression filterExpression = new FilterExpression(tag, FilterExpressionType.TAG);
SimpleConsumer consumer = provider.newSimpleConsumerBuilder()
.setClientConfiguration(clientConfiguration)
.setConsumerGroup(consumerGroup)
.setAwaitDuration(awaitDuration)
.setSubscriptionExpressions(Collections.singletonMap(topic, filterExpression))
.build();
// Maximum messages per pull
int maxMessageNum = 16;
// Messages stay invisible to other consumers for this duration after being received
Duration invisibleDuration = Duration.ofSeconds(10);
// Poll for messages in a loop. For real-time consumption, use multiple threads.
while (true) {
final List<MessageView> messages = consumer.receive(maxMessageNum, invisibleDuration);
messages.forEach(messageView -> {
System.out.println("Received message: " + messageView);
});
for (MessageView message : messages) {
final MessageId messageId = message.getMessageId();
try {
// ACK each message to commit the consumption result to the broker
consumer.ack(message);
System.out.println("Message is acknowledged successfully, messageId= " + messageId);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
// To shut down the consumer gracefully, call:
// consumer.close();
}
}
Verifique a entrega de mensagens
Verifique o status de entrega no console do ApsaraMQ for RocketMQ:
Acesse o console do ApsaraMQ for RocketMQ.
Na página Instances, clique no nome da instância.
No painel de navegação à esquerda, clique em Message Tracing.
Versões do SDK necessárias para acesso serverless pela Internet
O acesso a uma instância serverless do ApsaraMQ for RocketMQ pela Internet requer uma versão mínima do SDK. Substitua InstanceId nos exemplos pelo ID real da instância.
SDK para Java 5.x (rocketmq-client-java)
Versão mínima: 5.0.6
Defina o namespace em ClientConfiguration:
ClientConfiguration clientConfiguration = ClientConfiguration.newBuilder()
.setEndpoints(endpoints)
.setNamespace("InstanceId")
.setCredentialProvider(sessionCredentialsProvider)
.build();
SDK para Java 5.x (rocketmq-client)
Versão mínima: 5.2.0
Defina o namespace no produtor e no consumidor, separadamente:
// Producer
producer.setNamespaceV2("InstanceId");
// Consumer
consumer.setNamespaceV2("InstanceId");
SDK de cliente TCP para Java 1.x
Versão mínima: 1.9.0.Final
Defina o namespace por meio das propriedades:
properties.setProperty(PropertyKeyConst.Namespace, "InstanceId");
FAQ: E se ocorrer o erro "The instance version does not support setting user properties" ao enviar uma mensagem?
Esse erro geralmente ocorre devido a uma versão muito antiga do SDK. Para resolvê-lo, atualize o SDK para a versão 1.9.1.Final ou superior e tente novamente.
Próximos passos
Envie e receba mensagens em outras linguagens de programação. Veja a Visão geral do SDK.
Saiba mais sobre o PushConsumer e o SimpleConsumer.