As instâncias do ApsaraMQ for RocketMQ 5.x são compatíveis com o RocketMQ 1.x e 2.x SDK for .NET. Os exemplos a seguir mostram como enviar e receber mensagens normais, ordenadas, agendadas/atrasadas e transacionais.
Os SDKs mais recentes do RocketMQ 5.x oferecem total compatibilidade com brokers 5.x e incluem mais recursos. Para mais informações, consulte Release notes.
A Alibaba Cloud mantém os SDKs cliente do RocketMQ 3.x, 4.x e TCP apenas para cargas de trabalho existentes.
Pré-requisitos
Antes de executar o código de exemplo, prepare o ambiente. Para mais informações, consulte Prepare the environment.
Configuração comum
Todos os exemplos configuram ONSFactoryProperty com os parâmetros a seguir. Substitua os espaços reservados pelos valores reais.
|
Espaço reservado |
Descrição |
Exemplo |
|
|
Nome de usuário da instância disponível na aba Intelligent Authentication da página Access Control |
-- |
|
|
Senha da instância disponível na aba Intelligent Authentication da página Access Control |
-- |
|
|
Group ID criado no console do ApsaraMQ for RocketMQ |
|
|
|
Tópico criado no console do ApsaraMQ for RocketMQ |
|
|
|
Endpoint obtido no console do ApsaraMQ for RocketMQ (apenas domínio e porta — sem prefixo |
|
Use o nome de usuário e a senha da instância como AccessKey e SecretKey, não o par de AccessKey da sua conta Alibaba Cloud.
Não especifique o ID da instância ao acessar uma instância 5.x com o .NET SDK 1.x/2.x. Especificar o ID da instância causa falha na conexão.
Se o cliente for executado em uma instância ECS dentro de uma VPC, o broker obterá as credenciais automaticamente. Ignore a configuração de AccessKey e SecretKey.
Para instâncias serverless acessadas pela internet, sempre especifique o nome de usuário e a senha. Se você ativar a autenticação livre em VPCs para a instância serverless e se conectar de dentro de uma VPC, ignore as credenciais.
Mensagens normais
Enviar mensagens normais
using System;
using ons;
public class ProducerExampleForEx
{
public ProducerExampleForEx()
{
}
static void Main(string[] args) {
ONSFactoryProperty factoryInfo = new ONSFactoryProperty();
// Instance username and password from the Intelligent Authentication tab
// of the Access Control page in the ApsaraMQ for RocketMQ console.
// Do not use your Alibaba Cloud account AccessKey pair.
factoryInfo.setFactoryProperty(ONSFactoryProperty::AccessKey, "<your-instance-username>");
factoryInfo.setFactoryProperty(ONSFactoryProperty::SecretKey, "<your-instance-password>");
// Do not specify the instance ID for 5.x instances.
// Group ID created in the console.
factoryInfo.setFactoryProperty(ONSFactoryProperty.ProducerId, "<your-group-id>");
// Topic created in the console.
factoryInfo.setFactoryProperty(ONSFactoryProperty.PublishTopics, "<your-topic>");
// Endpoint from the console. Use domain:port only -- no http:// prefix, no resolved IP.
factoryInfo.setFactoryProperty(ONSFactoryProperty::NAMESRV_ADDR, "<your-endpoint>");
// Log path.
factoryInfo.setFactoryProperty(ONSFactoryProperty.LogPath, "C://log");
// Create a producer. Producers are thread-safe; in most cases, each thread requires only one instance.
Producer producer = ONSFactory.getInstance().createProducer(factoryInfo);
// Start the producer.
producer.start();
// Create and send messages.
Message msg = new Message(factoryInfo.getPublishTopics(), "tagA", "Example message body");
msg.setKey(Guid.NewGuid().ToString());
for (int i = 0; i < 32; i++) {
try
{
SendResultONS sendResult = producer.send(msg);
Console.WriteLine("send success {0}", sendResult.getMessageId());
}
catch (Exception ex)
{
Console.WriteLine("send failure{0}", ex.ToString());
}
}
// Shut down the producer before exiting the thread.
producer.shutdown();
}
}
Inscrever-se em mensagens normais
using System;
using System.Threading;
using System.Text;
using ons;
// Callback invoked when a message arrives from the broker.
public class MyMsgListener : MessageListener
{
public MyMsgListener()
{
}
~MyMsgListener()
{
}
public override ons.Action consume(Message value, ConsumeContext context)
{
Byte[] text = Encoding.Default.GetBytes(value.getBody());
Console.WriteLine(Encoding.UTF8.GetString(text));
return ons.Action.CommitMessage;
}
}
public class ConsumerExampleForEx
{
public ConsumerExampleForEx()
{
}
static void Main(string[] args) {
ONSFactoryProperty factoryInfo = new ONSFactoryProperty();
// Instance credentials from the Intelligent Authentication tab
// of the Access Control page. Do not use Alibaba Cloud account keys.
factoryInfo.setFactoryProperty(ONSFactoryProperty::AccessKey, "<your-instance-username>");
factoryInfo.setFactoryProperty(ONSFactoryProperty::SecretKey, "<your-instance-password>");
// Do not specify the instance ID for 5.x instances.
// Consumer group ID created in the console.
factoryInfo.setFactoryProperty(ONSFactoryProperty.ConsumerId, "<your-group-id>");
// Topic created in the console.
factoryInfo.setFactoryProperty(ONSFactoryProperty.PublishTopics, "<your-topic>");
// TCP endpoint from the Instance Details page in the console.
factoryInfo.setFactoryProperty(ONSFactoryProperty.NAMESRV_ADDR, "<your-endpoint>");
// Log path.
factoryInfo.setFactoryProperty(ONSFactoryProperty.LogPath, "C://log");
// Consumption mode: clustering (default) or broadcasting.
// factoryInfo.setFactoryProperty(ONSFactoryProperty:: MessageModel, ONSFactoryProperty.CLUSTERING);
// factoryInfo.setFactoryProperty(ONSFactoryProperty:: MessageModel, ONSFactoryProperty.BROADCASTING);
// Create a push consumer.
PushConsumer consumer = ONSFactory.getInstance().createPushConsumer(factoryInfo);
// Subscribe to the topic with a wildcard tag filter.
consumer.subscribe(factoryInfo.getPublishTopics(), "*", new MyMsgListener());
// Start the consumer.
consumer.start();
// Demo only. In production, keep the process running.
Thread.Sleep(300000);
// Shut down the consumer before exiting the process.
consumer.shutdown();
}
}
Mensagens ordenadas
Mensagens ordenadas garantem entrega FIFO para mensagens que compartilham a mesma chave de sharding.
Enviar mensagens ordenadas
A principal diferença em relação às mensagens normais é o uso de OrderProducer e a passagem de uma shardingKey para send(). Mensagens com a mesma chave de sharding são entregues em ordem.
using System;
using ons;
public class OrderProducerExampleForEx
{
public OrderProducerExampleForEx()
{
}
static void Main(string[] args) {
ONSFactoryProperty factoryInfo = new ONSFactoryProperty();
// Instance credentials.
factoryInfo.setFactoryProperty(ONSFactoryProperty::AccessKey, "<your-instance-username>");
factoryInfo.setFactoryProperty(ONSFactoryProperty::SecretKey, "<your-instance-password>");
// Do not specify the instance ID for 5.x instances.
factoryInfo.setFactoryProperty(ONSFactoryProperty.ProducerId, "<your-group-id>");
factoryInfo.setFactoryProperty(ONSFactoryProperty.PublishTopics, "<your-topic>");
factoryInfo.setFactoryProperty(ONSFactoryProperty::NAMESRV_ADDR, "<your-endpoint>");
factoryInfo.setFactoryProperty(ONSFactoryProperty.LogPath, "C://log");
// Create an order producer (not a regular Producer).
OrderProducer producer = ONSFactory.getInstance().createOrderProducer(factoryInfo);
producer.start();
Message msg = new Message(factoryInfo.getPublishTopics(), "tagA", "Example message body");
// Messages with the same sharding key are delivered in order.
string shardingKey = "App-Test";
for (int i = 0; i < 32; i++) {
try
{
SendResultONS sendResult = producer.send(msg, shardingKey);
Console.WriteLine("send success {0}", sendResult.getMessageId());
}
catch (Exception ex)
{
Console.WriteLine("send failure{0}", ex.ToString());
}
}
producer.shutdown();
}
}
Inscrever-se em mensagens ordenadas
Use OrderConsumer e implemente MessageOrderListener. Retorne OrderAction.Success em caso de sucesso ou OrderAction.Suspend para tentar novamente.
using System;
using System.Text;
using System.Threading;
using ons;
namespace demo
{
public class MyMsgOrderListener : MessageOrderListener
{
public MyMsgOrderListener()
{
}
~MyMsgOrderListener()
{
}
public override ons.OrderAction consume(Message value, ConsumeOrderContext context)
{
Byte[] text = Encoding.Default.GetBytes(value.getBody());
Console.WriteLine(Encoding.UTF8.GetString(text));
return ons.OrderAction.Success;
}
}
class OrderConsumerExampleForEx
{
static void Main(string[] args)
{
ONSFactoryProperty factoryInfo = new ONSFactoryProperty();
// Instance credentials.
factoryInfo.setFactoryProperty(ONSFactoryProperty::AccessKey, "<your-instance-username>");
factoryInfo.setFactoryProperty(ONSFactoryProperty::SecretKey, "<your-instance-password>");
// Do not specify the instance ID for 5.x instances.
factoryInfo.setFactoryProperty(ONSFactoryProperty.ProducerId, "<your-group-id>");
factoryInfo.setFactoryProperty(ONSFactoryProperty.PublishTopics, "<your-topic>");
factoryInfo.setFactoryProperty(ONSFactoryProperty::NAMESRV_ADDR, "<your-endpoint>");
factoryInfo.setFactoryProperty(ONSFactoryProperty.LogPath, "C://log");
// Create an order consumer (not a regular PushConsumer).
OrderConsumer consumer = ONSFactory.getInstance().createOrderConsumer(factoryInfo);
consumer.subscribe(factoryInfo.getPublishTopics(), "*",new MyMsgOrderListener());
consumer.start();
// Demo only. In production, keep the process running.
Thread.Sleep(30000);
consumer.shutdown();
}
}
}
Mensagens agendadas e atrasadas
Mensagens agendadas e atrasadas são entregues após um timestamp especificado. Defina o horário de entrega com setStartDeliverTime().
Enviar mensagens agendadas ou atrasadas
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using ons;
namespace ons
{
class onscsharp
{
static void Main(string[] args)
{
ONSFactoryProperty factoryInfo = new ONSFactoryProperty();
factoryInfo.setFactoryProperty(ONSFactoryProperty.ProducerId, "<your-group-id>");
factoryInfo.setFactoryProperty(ONSFactoryProperty::NAMESRV_ADDR, "<your-endpoint>");
factoryInfo.setFactoryProperty(ONSFactoryProperty.PublishTopics, "<your-topic>");
factoryInfo.setFactoryProperty(ONSFactoryProperty.MsgContent, "<your-message-content>");
// Instance credentials.
factoryInfo.setFactoryProperty(ONSFactoryProperty::AccessKey, "<your-instance-username>");
factoryInfo.setFactoryProperty(ONSFactoryProperty::SecretKey, "<your-instance-password>");
// Do not specify the instance ID for 5.x instances.
Producer pProducer = ONSFactory.getInstance().createProducer(factoryInfo);
// Call start() once before sending messages.
pProducer.start();
Message msg = new Message(
factoryInfo.getPublishTopics(),
"TagA",
factoryInfo.getMessageContent()
);
// Optional: set a business key for message tracing in the console.
msg.setKey("ORDERID_100");
// Set the delivery time in milliseconds. The message is delivered after this timestamp.
// In this example, the message is delivered 3 seconds from now.
long deliverTime = System.currentTimeMillis() + 3000;
msg.setStartDeliverTime(deliverTime);
try
{
SendResultONS sendResult = pProducer.send(msg);
}
catch(ONSClientException e)
{
// Handle the send failure.
}
// Shut down the producer before exiting. Skipping shutdown may cause memory leaks.
pProducer.shutdown();
}
}
}
Inscrever-se em mensagens agendadas ou atrasadas
Inscreva-se em mensagens agendadas e atrasadas da mesma forma que em mensagens normais. Para mais informações, consulte Inscrever-se em mensagens normais.
Mensagens transacionais
Mensagens transacionais usam commit de duas fases: envie uma half message com um executor de transação local e confirme o status da transação com um verificador. O broker chama o verificador se não receber um commit ou rollback dentro do tempo limite.
Enviar mensagens transacionais
Etapa 1: Enviar uma half message e executar a transação local
Implemente LocalTransactionExecuter para executar a lógica de negócios após o envio da half message. Retorne CommitTransaction, RollbackTransaction ou Unknow conforme o resultado.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using ons;
namespace ons
{
public class MyLocalTransactionExecuter : LocalTransactionExecuter
{
public MyLocalTransactionExecuter()
{
}
~MyLocalTransactionExecuter()
{
}
public override TransactionStatus execute(Message value)
{
Console.WriteLine("execute topic: {0}, tag:{1}, key:{2}, msgId:{3},msgbody:{4}, userProperty:{5}",
value.getTopic(), value.getTag(), value.getKey(), value.getMsgID(), value.getBody(), value.getUserProperty("VincentNoUser"));
// Use the message ID and a CRC32/MD5 hash of the body to deduplicate messages.
string msgId = value.getMsgID();
TransactionStatus transactionStatus = TransactionStatus.Unknow;
try {
boolean isCommit = Execution result of the local transaction;
if (isCommit) {
// Commit the message if the local transaction succeeds.
transactionStatus = TransactionStatus.CommitTransaction;
} else {
// Roll back the message if the local transaction fails.
transactionStatus = TransactionStatus.RollbackTransaction;
}
} catch (Exception e) {
// Handle the exception.
}
return transactionStatus;
}
}
class onscsharp
{
static void Main(string[] args)
{
ONSFactoryProperty factoryInfo = new ONSFactoryProperty();
factoryInfo.setFactoryProperty(ONSFactoryProperty::NAMESRV_ADDR, "<your-endpoint>");
factoryInfo.setFactoryProperty(ONSFactoryProperty.PublishTopics, "<your-topic>");
factoryInfo.setFactoryProperty(ONSFactoryProperty.MsgContent, "<your-message-content>");
// Instance credentials.
factoryInfo.setFactoryProperty(ONSFactoryProperty::AccessKey, "<your-instance-username>");
factoryInfo.setFactoryProperty(ONSFactoryProperty::SecretKey, "<your-instance-password>");
// Do not specify the instance ID for 5.x instances.
// Create a transaction producer with a transaction checker.
LocalTransactionChecker myChecker = new MyLocalTransactionChecker();
TransactionProducer pProducer =ONSFactory.getInstance().createTransactionProducer(factoryInfo,ref myChecker);
// Call start() once. After startup, send messages concurrently from multiple threads.
pProducer.start();
Message msg = new Message(
factoryInfo.getPublishTopics(),
"TagA",
factoryInfo.getMessageContent()
);
// Optional: set a business key for message tracing in the console.
msg.setKey("ORDERID_100");
try
{
LocalTransactionExecuter myExecuter = new MyLocalTransactionExecuter();
SendResultONS sendResult = pProducer.send(msg, ref myExecuter);
}
catch(ONSClientException e)
{
Console.WriteLine("\nexception of sendmsg:{0}",e.what() );
}
// Shut down the producer before exiting. The producer cannot be restarted after shutdown.
pProducer.shutdown();
}
}
}
Etapa 2: Implementar o verificador de status da transação
O broker invoca LocalTransactionChecker.check() para verificar o status da transação quando não recebe um commit ou rollback. Implemente lógica idempotente para lidar com chamadas de verificação repetidas.
public class MyLocalTransactionChecker : LocalTransactionChecker
{
public MyLocalTransactionChecker()
{
}
~MyLocalTransactionChecker()
{
}
public override TransactionStatus check(Message value)
{
Console.WriteLine("check topic: {0}, tag:{1}, key:{2}, msgId:{3},msgbody:{4}, userProperty:{5}",
value.getTopic(), value.getTag(), value.getKey(), value.getMsgID(), value.getBody(), value.getUserProperty("VincentNoUser"));
// Use the message ID and a CRC32/MD5 hash of the body to deduplicate.
string msgId = value.getMsgID();
TransactionStatus transactionStatus = TransactionStatus.Unknow;
try {
boolean isCommit = Execution result of the local transaction;
if (isCommit) {
// Commit the message if the local transaction succeeded.
transactionStatus = TransactionStatus.CommitTransaction;
} else {
// Roll back the message if the local transaction failed.
transactionStatus = TransactionStatus.RollbackTransaction;
}
} catch (Exception e) {
// Handle the exception.
}
return transactionStatus;
}
}
Inscrever-se em mensagens transacionais
Inscreva-se em mensagens transacionais da mesma forma que em mensagens normais. Para mais informações, consulte Inscrever-se em mensagens normais.
Referências
Preparar o ambiente — configure o .NET SDK.
SDK overview — códigos de exemplo para outras linguagens.
-
Tipos de mensagem: