Utilisez le SDK Simple Message Queue (SMQ, anciennement MNS) pour Java afin d'extraire les messages d'une file d'attente, de les traiter et de les supprimer après consommation.
Prérequis
Avant de commencer, assurez-vous d'avoir :
Installé le SDK SMQ pour Java. Consultez la rubrique Installation du SDK pour Java
Configuré un endpoint et des identifiants d'accès. Consultez la rubrique Configuration des endpoints et des identifiants d'accès
Informations sur l'autorisation
Par défaut, seul un compte Alibaba Cloud peut appeler cette opération. Pour l'appeler en tant qu'utilisateur Resource Access Management (RAM), accordez-lui d'abord les autorisations requises.
|
Nom |
Valeur |
|
API |
ReceiveMessage |
|
Action |
mns:ReceiveMessage |
|
Ressource |
acs:mns:$region:$accountid:/queues/$queueName/messages |
Fonctionnement de la réception des messages
Lorsqu'un consommateur appelle ReceiveMessage , le message passe de l'état Active à l'état Inactive pendant la durée définie par le paramètre VisibilityTimeout .
Supprimez le message dans ce délai de visibilité en appelant DeleteMessage. Si vous ne supprimez pas le message à temps, il revient à l'état Active et redevient disponible pour la consommation.
Encodage du corps du message
L'encodage Base64 est désactivé par défaut. La propriété msgBodyBase64Switch de votre fichier de configuration est définie sur false par défaut. Si le corps de votre message ne contient aucun caractère spécial, utilisez les méthodes de chaîne brute :
Envoi : appelez
message.setMessageBodyAsRawString.Réception : appelez
message.getMessageBodyAsRawString.
Méthodes de réception
Le SDK propose deux méthodes pour recevoir des messages. Privilégiez la réception par lots avec interrogation longue (long polling) en production pour un débit plus élevé et moins d'appels API.
|
Méthode |
Appel API |
Cas d'utilisation |
|
Réception unique |
|
Scénarios à faible débit ou tests rapides. |
|
Réception par lots avec interrogation longue (recommandée) |
|
Charges de travail en production. Reçoit jusqu'à |
L'interrogation longue maintient la connexion ouverte pendant la durée spécifiée par waitSeconds et renvoie les messages dès qu'ils sont disponibles, au lieu de retourner immédiatement une réponse vide. Cette approche réduit le nombre de réponses vides et d'appels API par rapport à l'interrogation courte.
Exemple de code
Pour obtenir le code source complet et exécutable, consultez la page ReceiveMessageDemo sur GitHub.
Configuration
Créez ou mettez à jour le fichier ${"user.home"}/.aliyun-mns.properties avec votre endpoint et votre préférence d'encodage Base64 :
mns.endpoint=http://xxxxxxx
mns.msgBodyBase64Switch=true/false
Stockez votre ID AccessKey et votre secret AccessKey en tant que variables d'environnement, conformément aux bonnes pratiques de sécurité d'Alibaba Cloud.
Code
L'exemple effectue une boucle continue, en alternant entre une réception unique et une réception par lots avec interrogation longue. Chaque message reçu est affiché, puis supprimé.
package com.aliyun.mns.sample.queue;
import com.aliyun.mns.client.CloudAccount;
import com.aliyun.mns.client.CloudQueue;
import com.aliyun.mns.client.MNSClient;
import com.aliyun.mns.common.ClientException;
import com.aliyun.mns.common.ServiceException;
import com.aliyun.mns.common.ServiceHandlingRequiredException;
import com.aliyun.mns.common.utils.ServiceSettings;
import com.aliyun.mns.model.Message;
import java.util.List;
/**
* Prerequisites:
* 1. Set the AccessKey ID and AccessKey secret as environment variables following Alibaba Cloud security best practices.
* 2. Create ${"user.home"}/.aliyun-mns.properties with the following content:
* mns.endpoint=http://xxxxxxx
* mns.msgBodyBase64Switch=true/false
*/
public class ReceiveMessageDemo {
/**
* Whether to decode the message body from Base64.
*/
private static final Boolean IS_BASE64 = Boolean.valueOf(ServiceSettings.getMNSPropertyValue("msgBodyBase64Switch","false"));
public static void main(String[] args) {
String queueName = "cloud-queue-demo";
// Set the AccessKey ID and AccessKey secret as environment variables following Alibaba Cloud security best practices.
CloudAccount account = new CloudAccount(ServiceSettings.getMNSAccountEndpoint());
// Initialize the client once and reuse it.
MNSClient client = account.getMNSClient();
CloudQueue queue = client.getQueueRef(queueName);
// Receive and process messages in a loop.
loopReceive(queue, client);
// Close the client after processing.
client.close();
}
private static void loopReceive(CloudQueue queue, MNSClient client) {
while (true) {
try {
// Single receive: basic method.
singleReceive(queue);
// Long polling batch receive: recommended for production.
longPollingBatchReceive(queue);
} catch (ClientException ce) {
System.out.println("Network connection error between client and SMQ service. "
+ "Check your network and DNS settings.");
// Retry on transient network errors.
} catch (ServiceException se) {
if (se.getErrorCode().equals("QueueNotExist")) {
System.out.println("Queue does not exist. Create the queue before calling ReceiveMessage.");
client.close();
return;
} else if (se.getErrorCode().equals("TimeExpired")) {
System.out.println("Request expired. Check your local machine clock for time synchronization issues.");
return;
}
// Retry on transient service errors.
} catch (Exception e) {
System.out.println("Unexpected error: " + e.getMessage());
}
}
}
private static void longPollingBatchReceive(CloudQueue queue) throws ServiceHandlingRequiredException {
System.out.println("=============start longPollingBatchReceive=============");
// Maximum number of messages to receive per call.
int batchSize = 15;
// Long polling wait time in seconds.
int waitSeconds = 15;
List<Message> messages = queue.batchPopMessage(batchSize, waitSeconds);
if (messages != null && messages.size() > 0) {
for (Message message : messages) {
printMsgAndDelete(queue,message);
}
}
System.out.println("=============end longPollingBatchReceive=============");
}
private static void singleReceive(CloudQueue queue) throws ServiceHandlingRequiredException {
System.out.println("=============start singleReceive=============");
Message popMsg = queue.popMessage();
printMsgAndDelete(queue, popMsg);
System.out.println("=============end singleReceive=============");
}
private static void printMsgAndDelete(CloudQueue queue, Message popMsg) throws ServiceHandlingRequiredException {
if (popMsg != null) {
System.out.println("message handle: " + popMsg.getReceiptHandle());
System.out.println("message body: " + (IS_BASE64 ? popMsg.getMessageBody() : popMsg.getMessageBodyAsRawString()));
System.out.println("message id: " + popMsg.getMessageId());
System.out.println("message dequeue count:" + popMsg.getDequeueCount());
// Add your message processing logic here.
// Delete the message after successful consumption.
queue.deleteMessage(popMsg.getReceiptHandle());
System.out.println("delete message successfully.\n");
}
}
}
Gestion des erreurs
La boucle intercepte trois types d'exceptions. Traitez-les comme suit :
|
Type d'exception |
Cause |
Action de récupération |
|
|
Problèmes de connexion réseau entre le client et le service SMQ |
Réessayez. Vérifiez vos paramètres réseau et DNS. |
|
|
La file d'attente spécifiée n'existe pas |
Créez la file d'attente avant d'appeler ReceiveMessage. |
|
|
La demande a expiré |
Vérifiez l'horloge de votre machine locale pour détecter d'éventuels problèmes de synchronisation temporelle. |
|
|
Erreurs inconnues |
Réessayez. Consignez l'erreur pour une investigation ultérieure. |
Sortie attendue
Une exécution réussie produit une sortie similaire à celle ci-dessous. Chaque bloc affiche le receipt handle, le corps du message, l'ID du message et le nombre de retraits (dequeue count) avant de confirmer la suppression.
=============start singleReceive=============
message handle: 1-ODU4OTkzNDU5My0xNDMyNzI3ODI3LTItOA==
message body: This is a test message
message id: 5F290C926D472878-2-14D9529A8FA-20000****
message dequeue count:1
delete message successfully.
=============end singleReceive=============
=============start longPollingBatchReceive=============
message handle: 1-ODU4OTkzNDU5My0xNDMyNzI3MzI3LTItOA==
message body: Batch message 1
message id: 5F290C926D472878-2-14D9529A8FA-20001****
message dequeue count:1
delete message successfully.
message handle: 1-ODU4OTkzNDU5My0xNDMyNzI3NDI3LTItOA==
message body: Batch message 2
message id: 5F290C926D472878-2-14D9529A8FA-20002****
message dequeue count:1
delete message successfully.
=============end longPollingBatchReceive=============