Después de crear los recursos de ApsaraMQ for RocketMQ, como un topic y un consumer group, puede integrar la mensajería en su aplicación Java. Esta guía muestra cómo agregar la dependencia del SDK para Java 5.x, conectarse a su instancia, enviar mensajes normales y consumirlos con un push consumer o un simple consumer.
Antes de empezar
Asegúrese de contar con lo siguiente:
Created resources en ApsaraMQ for RocketMQ, incluidos un topic y un consumer group (paso 2 de esta serie)
Un IDE de Java como IntelliJ IDEA o Eclipse (los ejemplos usan IntelliJ IDEA Ultimate)
Agregue la dependencia del SDK
Cree un proyecto de Java en su IDE.
-
Agregue la siguiente dependencia al archivo
pom.xml:<dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-client-java</artifactId> <version>5.0.7</version> </dependency>
**Preguntas frecuentes: ¿Qué hago si aparece el error ClassNotFoundException: com.google.protobuf.GeneratedMessageV3 después de agregar la dependencia rocketmq-client-java?**
Este error suele deberse a un conflicto de dependencias. Una dependencia más antigua del proyecto, como rocketmq-spring-boot-starter, interfiere con la carga de clases de Protobuf.
Para resolver este problema:
Verifique que el proyecto incluya la dependencia correcta de
protobuf-java. También puede aislar los SDK de distintas versiones en módulos separados para evitar el conflicto.Si no es posible separar los SDK en módulos distintos, agregue explícitamente las dependencias
rocketmq-protoyprotobuf-java.
El SDK rocketmq-client-java que utiliza el simple consumer ya incluye una versión sombreada (shaded) de Protobuf (org.apache.rocketmq.shaded.com.google.protobuf). En la mayoría de los casos, no es necesario agregar com.google.protobuf:protobuf-java por separado.
Recopile los parámetros de conexión
Obtenga los siguientes valores desde la consola de ApsaraMQ for RocketMQ antes de escribir código:
|
Parámetro |
Ejemplo |
Dónde encontrarlo |
|
|
|
Página Instance Details > pestaña Endpoints. Use el endpoint de VPC cuando acceda a la instancia desde una instancia de Elastic Compute Service (ECS) en la misma VPC, o bien el endpoint público para acceder por Internet. Consulte Get the endpoint of an instance. |
|
|
|
El topic que creó para enviar y recibir mensajes. Debe crearse previamente. Consulte Create a topic. |
|
|
|
El consumer group que creó. Debe crearse previamente. Consulte Create a consumer group. |
|
|
|
El ID de su instancia de ApsaraMQ for RocketMQ. Es obligatorio solo para instancias serverless a las que se accede por Internet. |
|
Nombre de usuario de la instancia |
|
Página Access Control > pestaña Intelligent Authentication. Consulte Get the username and password of an instance. |
|
Contraseña de la instancia |
|
En la misma ubicación que el nombre de usuario. |
Cuándo se requieren credenciales
La necesidad de proporcionar un nombre de usuario, una contraseña y un namespace depende del método de acceso:
|
Método de acceso |
Nombre de usuario y contraseña |
Namespace (ID de instancia) |
|
VPC (instancia estándar) |
No es obligatorio. El broker obtiene las credenciales automáticamente a partir de la información de la VPC. |
No es obligatorio. |
|
VPC (instancia serverless, autenticación sin credenciales habilitada) |
No es obligatorio. |
No es obligatorio. |
|
VPC (instancia serverless, autenticación sin credenciales deshabilitada) |
Obligatorio. |
No es obligatorio. |
|
Internet (instancia estándar) |
Obligatorio. Primero habilite el acceso por Internet en la instancia. |
No es obligatorio. |
|
Internet (instancia serverless) |
Obligatorio. |
Obligatorio. Se establece mediante |
Envíe mensajes
Cree un archivo ProducerExample.java en su proyecto y ejecútelo:
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();
}
}
}
Reemplace los marcadores de posición con sus valores:
|
Marcador de posición |
Descripción |
|
|
Endpoint de la instancia, por ejemplo, |
|
|
Nombre del topic, por ejemplo, |
|
|
ID de la instancia (solo para acceso por Internet en modalidad serverless) |
|
|
Nombre de usuario de la instancia (acceso por Internet o VPC serverless sin autenticación sin credenciales) |
|
|
Contraseña de la instancia (acceso por Internet o VPC serverless sin autenticación sin credenciales) |
.setTopics()
durante la inicialización del producer valida la configuración del topic de forma anticipada. Este paso es opcional para los mensajes normales, ya que se validan dinámicamente al momento del envío. Sin embargo, es obligatorio para los mensajes transaccionales, pues evita fallos en las API de consulta.
Si falla el envío de un mensaje, este no se escribe en el servidor. Por lo tanto, no podrá buscarlo por su ID en la consola más adelante. En el código de su aplicación, capture la excepción (por ejemplo, en SendCallback.onException), registre el contenido completo del mensaje y reintente el envío según su lógica de negocio.
Reciba mensajes
ApsaraMQ for RocketMQ ofrece dos tipos de consumidores:
|
Push consumer |
Simple consumer |
|
|
Funcionamiento |
El SDK entrega los mensajes a una función de devolución de llamada (listener de mensajes). |
Su aplicación extrae los mensajes y confirma cada uno de manera explícita. |
|
Concurrencia |
La gestiona el SDK. |
La gestiona su aplicación. |
|
Flexibilidad |
Menor. El SDK encapsula el flujo de consumo. |
Mayor. Las operaciones atómicas permiten construir flujos de trabajo personalizados. |
|
Casos de uso recomendados |
La mayoría de los escenarios donde necesita procesar mensajes entrantes. |
Escenarios que requieren un control detallado sobre la extracción, el procesamiento o la confirmación. |
Comience con un push consumer, a menos que necesite un control personalizado sobre el flujo de consumo.
Si usa rocketmq-spring-boot-starter o rocketmq-v5-client-spring-boot-starter para integrar el SDK con Spring Boot, tenga en cuenta las siguientes limitaciones y diferencias de configuración:
La anotación
@RocketMQMessageListenerde rocketmq-spring-boot-starter solo admite el push consumer. Si necesita un simple consumer, debe inicializarlo manualmente en el código, ya que la anotación no lo admite.En rocketmq-v5-client-spring-boot-starter, el simple consumer y los cambios dinámicos en su duración de invisibilidad también requieren inicialización manual en el código. No se inyectan automáticamente mediante anotaciones.
En el archivo de configuración del starter v5, utilice el parámetro
endpointsen lugar del parámetro anteriorname-server.El parámetro de namespace varía según el starter: con rocketmq-v5-client-spring-boot-starter, configure
namespace; con rocketmq-spring-boot-starter, configurenamespaceV2. Si su archivo de configuración YAML no admite este parámetro, establézcalo en el código.
Push consumer
Cree un archivo PushConsumerExample.java y ejecútelo:
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();
}
}
El push consumer del SDK gRPC 5.x de ApsaraMQ for RocketMQ utiliza una cola de búfer local interna. Incluso con un consumo de un solo hilo, el SDK precarga mensajes en este búfer. Si su lógica de negocio tarda mucho en procesar cada mensaje, esta precarga puede provocar tiempos de espera locales y un uso innecesario de recursos.
Para lógicas de negocio de larga duración, utilice un simple consumer (modo pull). Un simple consumer le permite controlar exactamente cuántos mensajes se extraen a la vez. Además, extraerá el siguiente lote solo después de procesar y confirmar el actual. Puede establecer InvisibleDuration (el periodo durante el cual un mensaje recibido permanece invisible para otros consumidores, de 10 segundos a 12 horas) para controlar el tiempo de espera de confirmación y ampliarlo dinámicamente si es necesario.
Simple consumer
Cree un archivo SimpleConsumerExample.java y ejecútelo:
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();
}
}
Compruebe la entrega de mensajes
Revise el estado de entrega en la consola de ApsaraMQ for RocketMQ:
Inicie sesión en la consola de ApsaraMQ for RocketMQ.
En la página Instances, haga clic en el nombre de su instancia.
En el panel de navegación izquierdo, haga clic en Message Tracing.
Versiones del SDK obligatorias para el acceso serverless por Internet
Acceder a una instancia serverless de ApsaraMQ for RocketMQ por Internet requiere una versión mínima del SDK. Reemplace InstanceId en los ejemplos con el ID real de su instancia.
SDK for Java 5.x (rocketmq-client-java)
Versión mínima: 5.0.6
Establezca el namespace en ClientConfiguration:
ClientConfiguration clientConfiguration = ClientConfiguration.newBuilder()
.setEndpoints(endpoints)
.setNamespace("InstanceId")
.setCredentialProvider(sessionCredentialsProvider)
.build();
SDK for Java 5.x (rocketmq-client)
Versión mínima: 5.2.0
Establezca el namespace en el producer y en el consumer por separado:
// Producer
producer.setNamespaceV2("InstanceId");
// Consumer
consumer.setNamespaceV2("InstanceId");
TCP client SDK for Java 1.x
Versión mínima: 1.9.0.Final
Establezca el namespace mediante propiedades:
properties.setProperty(PropertyKeyConst.Namespace, "InstanceId");
Preguntas frecuentes: ¿Qué hago si aparece el error "The instance version does not support setting user properties" al enviar un mensaje?
Este error suele deberse a una versión demasiado antigua del SDK. Para resolverlo, actualice su SDK a la versión 1.9.1.Final o posterior e inténtelo de nuevo.
Pasos siguientes
Envíe y reciba mensajes en otros lenguajes de programación. Consulte SDK overview.
Obtenga más información sobre PushConsumer y SimpleConsumer.