Une fois les ressources ApsaraMQ for RocketMQ créées (topic et groupe de consommateurs), vous pouvez intégrer la messagerie à votre application Java. Ce guide explique comment ajouter la dépendance du SDK Java 5.x, vous connecter à votre instance, envoyer des messages normaux et les consommer via un push consumer ou un simple consumer.
Avant de commencer
Vérifiez que vous disposez des éléments suivants :
Ressources créées dans ApsaraMQ for RocketMQ, notamment un topic et un groupe de consommateurs (étape 2 de cette série)
Un IDE Java tel que IntelliJ IDEA ou Eclipse (les exemples utilisent IntelliJ IDEA Ultimate)
Ajouter la dépendance du SDK
Créez un projet Java dans votre IDE.
-
Ajoutez la dépendance suivante au fichier
pom.xml:<dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-client-java</artifactId> <version>5.0.7</version> </dependency>
**FAQ : Que faire si l'erreur ClassNotFoundException: com.google.protobuf.GeneratedMessageV3 survient après l'ajout de la dépendance rocketmq-client-java ?**
Cette erreur résulte généralement d'un conflit de dépendances : une dépendance plus ancienne de votre projet, telle que rocketmq-spring-boot-starter, interfère avec le chargement des classes Protobuf.
Pour résoudre ce problème :
Vérifiez que votre projet inclut la bonne dépendance
protobuf-java, ou isolez les SDK de différentes versions dans des modules distincts pour éviter le conflit.Si vous ne pouvez pas séparer les SDK en modules distincts, ajoutez explicitement les dépendances
rocketmq-protoetprotobuf-java.
Le SDK rocketmq-client-java utilisé par le simple consumer intègre déjà une version ombragée (shaded) de Protobuf (org.apache.rocketmq.shaded.com.google.protobuf). Dans la plupart des cas, il n'est pas nécessaire d'ajouter séparément com.google.protobuf:protobuf-java.
Rassembler les paramètres de connexion
Récupérez les valeurs suivantes depuis la console ApsaraMQ for RocketMQ avant d'écrire le code :
| Paramètre | Exemple | Où le trouver |
|---|---|---|
endpoints |
rmq-cn-xxx.{regionId}.rmq.aliyuncs.com:8080 |
Page Instance Details > onglet Endpoints. Utilisez l'endpoint VPC lorsque vous accédez à l'instance depuis une instance Elastic Compute Service (ECS) dans le même VPC, ou l'endpoint public pour un accès Internet. Consultez la rubrique Obtenir l'endpoint d'une instance. |
topic |
normal_test |
Le topic créé pour l'envoi et la réception de messages. Il doit être précréé. Consultez la rubrique Créer un topic. |
consumerGroup |
GID_test |
Le groupe de consommateurs créé. Il doit être précréé. Consultez la rubrique Créer un groupe de consommateurs. |
InstanceId |
rmq-cn-xxx |
L'ID de votre instance ApsaraMQ for RocketMQ. Requis uniquement pour les instances serverless accessibles via Internet. |
| Nom d'utilisateur de l'instance | 1XVg0hzgKm****** |
Page Access Control > onglet Intelligent Authentication. Consultez la rubrique Obtenir le nom d'utilisateur et le mot de passe d'une instance. |
| Mot de passe de l'instance | ijSt8rEc45****** |
Même emplacement que le nom d'utilisateur. |
Lorsque les identifiants sont requis
La nécessité de fournir un nom d'utilisateur, un mot de passe et un namespace dépend de votre méthode d'accès :
| Méthode d'accès | Nom d'utilisateur et mot de passe | Namespace (ID d'instance) |
|---|---|---|
| VPC (instance standard) | Non requis. Le broker obtient automatiquement les identifiants à partir des informations VPC. | Non requis. |
| VPC (instance serverless, authentification sans mot de passe activée) | Non requis. | Non requis. |
| VPC (instance serverless, authentification sans mot de passe désactivée) | Requis. | Non requis. |
| Internet (instance standard) | Requis. Activez d'abord l'accès Internet sur l'instance. | Non requis. |
| Internet (instance serverless) | Requis. | Requis. Définissez-le via .setNamespace("InstanceId"). |
Envoyer des messages
Créez un fichier ProducerExample.java dans votre projet et exécutez-le :
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();
}
}
}
Remplacez les espaces réservés par vos valeurs :
| Espace réservé | Description |
|---|---|
<your-endpoint> |
Endpoint de l'instance, par exemple rmq-cn-xxx.cn-hangzhou.rmq.aliyuncs.com:8080 |
<your-topic> |
Nom du topic, par exemple normal_test |
<your-instance-id> |
ID de l'instance (uniquement pour l'accès Internet serverless) |
<instance-username> |
Nom d'utilisateur de l'instance (accès Internet ou VPC serverless sans authentification sans mot de passe) |
<instance-password> |
Mot de passe de l'instance (accès Internet ou VPC serverless sans authentification sans mot de passe) |
L'appel à .setTopics() lors de l'initialisation du producteur valide les paramètres du topic en amont. Cette étape est facultative pour les messages normaux (validés dynamiquement au moment de l'envoi), mais requise pour les messages transactionnels afin d'éviter les échecs de l'API de requête.
Si l'envoi d'un message échoue, celui-ci n'est pas écrit sur le serveur ; vous ne pourrez donc pas le rechercher par son ID de message dans la console ultérieurement. Dans le code de votre application, interceptez l'exception (par exemple, dans SendCallback.onException), journalisez le contenu complet du message et réessayez l'envoi selon votre logique métier.
Recevoir des messages
ApsaraMQ for RocketMQ propose deux types de consommateurs :
| Push consumer | Simple consumer | |
|---|---|---|
| Fonctionnement | Le SDK délivre les messages à un callback (écouteur de messages). | Votre application extrait les messages et accuse réception de chacun d'eux de manière explicite. |
| Concurrence | Gérée par le SDK. | Gérée par votre application. |
| Flexibilité | Plus faible. Le SDK encapsule le flux de consommation. | Plus élevée. Les opérations atomiques vous permettent de créer des workflows personnalisés. |
| Meilleur usage | La plupart des cas d'utilisation nécessitant le traitement des messages entrants. | Scénarios nécessitant un contrôle précis de l'extraction, du traitement ou de l'accusé de réception. |
Privilégiez le push consumer, sauf si vous avez besoin d'un contrôle personnalisé sur le flux de consommation.
Si vous utilisez rocketmq-spring-boot-starter ou rocketmq-v5-client-spring-boot-starter pour intégrer le SDK à Spring Boot, tenez compte des limitations et différences de configuration suivantes :
L'annotation
@RocketMQMessageListenerdans rocketmq-spring-boot-starter prend uniquement en charge le push consumer. Si vous avez besoin d'un simple consumer, vous devez l'initialiser manuellement dans le code ; l'annotation ne le prend pas en charge.Dans rocketmq-v5-client-spring-boot-starter, le simple consumer et les modifications dynamiques de sa durée d'invisibilité nécessitent également une initialisation manuelle dans le code. Ils ne sont pas injectés automatiquement via des annotations.
Dans le fichier de configuration du starter v5, utilisez le paramètre
endpointsau lieu du paramètrename-serverutilisé précédemment.Le paramètre namespace diffère selon le starter : avec rocketmq-v5-client-spring-boot-starter, configurez
namespace; avec rocketmq-spring-boot-starter, configurez plutôtnamespaceV2. Si votre fichier de configuration YAML ne prend pas en charge ce paramètre, définissez-le dans le code.
Push consumer
Créez un fichier PushConsumerExample.java et exécutez-le :
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();
}
}
Le push consumer du SDK gRPC ApsaraMQ for RocketMQ 5.x utilise une file d'attente tampon locale interne. Même avec une consommation monothread, le SDK précharge les messages dans ce tampon. Si votre logique métier met beaucoup de temps à traiter chaque message, ce préchargement peut entraîner des délais d'attente locaux et une utilisation inutile des ressources.
Pour une logique métier longue, privilégiez un simple consumer (mode extraction). Un simple consumer vous permet de contrôler exactement le nombre de messages extraits à la fois ; vous n'extrayez le lot suivant qu'après avoir traité et accusé réception du lot actuel. Vous pouvez définir InvisibleDuration (la période pendant laquelle un message reçu reste invisible pour les autres consommateurs, de 10 secondes à 12 heures) pour contrôler le délai d'expiration de l'accusé de réception, et l'étendre dynamiquement si nécessaire.
Simple consumer
Créez un fichier SimpleConsumerExample.java et exécutez-le :
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();
}
}
Vérifier la livraison des messages
Vérifiez l'état de la livraison dans la console ApsaraMQ for RocketMQ :
Connectez-vous à la console ApsaraMQ for RocketMQ.
Sur la page Instances, cliquez sur le nom de votre instance.
Dans le volet de navigation de gauche, cliquez sur Message Tracing.
Versions de SDK requises pour l'accès Internet serverless
L'accès à une instance ApsaraMQ for RocketMQ serverless via Internet nécessite une version minimale du SDK. Remplacez InstanceId dans les exemples par votre ID d'instance réel.
SDK for Java 5.x (rocketmq-client-java)
Version minimale : 5.0.6
Définissez le namespace dans ClientConfiguration :
ClientConfiguration clientConfiguration = ClientConfiguration.newBuilder()
.setEndpoints(endpoints)
.setNamespace("InstanceId")
.setCredentialProvider(sessionCredentialsProvider)
.build();
SDK for Java 5.x (rocketmq-client)
Version minimale : 5.2.0
Définissez le namespace séparément sur le producteur et le consommateur :
// Producer
producer.setNamespaceV2("InstanceId");
// Consumer
consumer.setNamespaceV2("InstanceId");
TCP client SDK for Java 1.x
Version minimale : 1.9.0.Final
Définissez le namespace via les propriétés :
properties.setProperty(PropertyKeyConst.Namespace, "InstanceId");
FAQ : Que faire si l'erreur « The instance version does not support setting user properties » survient lors de l'envoi d'un message ?
Cette erreur résulte généralement d'une version du SDK trop ancienne. Pour la résoudre, mettez à jour votre SDK vers la version 1.9.1.Final ou ultérieure, puis réessayez.
Étapes suivantes
Envoyez et recevez des messages dans d'autres langages de programmation. Consultez la rubrique Présentation des SDK.
En savoir plus sur PushConsumer et SimpleConsumer.