YMJake.RocketMQ
0.1.0-preview.2
dotnet add package YMJake.RocketMQ --version 0.1.0-preview.2
NuGet\Install-Package YMJake.RocketMQ -Version 0.1.0-preview.2
<PackageReference Include="YMJake.RocketMQ" Version="0.1.0-preview.2" />
<PackageVersion Include="YMJake.RocketMQ" Version="0.1.0-preview.2" />
<PackageReference Include="YMJake.RocketMQ" />
paket add YMJake.RocketMQ --version 0.1.0-preview.2
#r "nuget: YMJake.RocketMQ, 0.1.0-preview.2"
#:package YMJake.RocketMQ@0.1.0-preview.2
#addin nuget:?package=YMJake.RocketMQ&version=0.1.0-preview.2&prerelease
#tool nuget:?package=YMJake.RocketMQ&version=0.1.0-preview.2&prerelease
YMJake.RocketMQ
An unofficial Apache RocketMQ client for .NET, speaking the RocketMQ 5.x gRPC proxy protocol.
It ships net8.0 and net10.0 targets and exposes typed, task-based APIs for the Producer,
SimpleConsumer, PushConsumer, and the lite-topic consumers. The client half of the protocol is
implemented from scratch: settings registration, the telemetry stream, queue assignment, long
polling, receipt handles, message-body integrity checks, and reconnect.
Preview. The package is
0.1.0-preview.1. The public API may still change before1.0.
Requirements
- .NET 8 SDK or newer; the library targets
net8.0andnet10.0. - A RocketMQ 5.x deployment with the proxy enabled (gRPC, default port
8081). The client connects to the proxy access point, not to a NameServer or Broker address. - Lite topics need a lite-enabled deployment;
LiteSimpleConsumeradditionally needs RocketMQ 5.5.1 or later, because older proxies rejectLITE_SIMPLE_CONSUMER.
Install
dotnet add package YMJake.RocketMQ --prerelease
The package ID and the namespace differ; the code is imported with:
using RocketMQ.Client;
Features and status
✅ means the client implements the API. The corresponding server-side capability and
configuration still apply.
| Feature | Status | Notes |
|---|---|---|
| Producer with standard messages | ✅ | IProducer.SendAsync. |
| Producer with batch messages | ✅ | One topic per request and a single receipt; FIFO messages are not allowed; a partially failed batch throws. |
| Producer with FIFO messages | ✅ | Set Message.MessageGroup; the topic must be a FIFO topic. |
| Producer with timed/delay messages | ✅ | Set Message.DeliveryTimestamp. |
| Producer with priority messages | ✅ | Set Message.Priority; servers without priority queues ignore it. |
| Producer with transactional messages | ✅ | BeginTransaction / ITransaction.Commit / Rollback; a TransactionChecker resolves orphaned half messages. |
| Recalling timed messages | ✅ | RecallAsync with the RecallHandle of the send receipt, before delivery. |
| Lite producer messages | ✅ | Set Message.LiteTopic; LiteTopicQuotaExceededException reports an exhausted quota. |
| Simple consumer | ✅ | ReceiveAsync, AckAsync, ChangeInvisibleDurationAsync, runtime subscribe/unsubscribe. |
| Push consumer with concurrent listener | ✅ | Background long polling; WorkersPerQueue listeners consume one assigned queue concurrently. |
| Push consumer with FIFO listener | ✅ | FIFO groups consume one queue with a single worker, so each MessageGroup stays ordered. |
| Push retry and dead-letter handling | ✅ | A failed listener is redelivered after the server retry policy's backoff; after MaxAttempts the message is forwarded to the dead-letter queue. |
| Runtime subscriptions | ✅ | SubscribeAsync / Unsubscribe on push and simple consumers. |
| LitePushConsumer | ✅ | SubscribeLiteAsync / UnsubscribeLiteAsync at runtime, OffsetOption on first subscription, quota and limit tracking from the proxy. |
| LiteSimpleConsumer | ✅ | The lite subscription set plus explicit receive, ack, and invisible-duration changes. |
| Tag and SQL filtering | ✅ | FilterExpression with ExpressionType.Tag or ExpressionType.Sql92; SQL filtering needs the server's filtering configuration. |
| Credentials and request signing | ✅ | Pluggable ICredentialsProvider, StaticCredentialsProvider, ACL signature on every request. |
| Message-body integrity | ✅ | CRC32/MD5/SHA1 digest verification and GZIP/ZLIB decoding; failures surface as MessageView.IsCorrupted. |
| Telemetry, settings sync, and reconnect | ✅ | Telemetry stream, heartbeats, periodic route and settings refresh, automatic reconnect with backoff. |
| Typed errors | ✅ | Proxy status codes map to RocketMQ.Client.Exceptions types. |
Intentionally not included: the classic Remoting protocol, an admin API, Microsoft dependency injection / Generic Host integration, and OpenTelemetry metrics or tracing.
Quick start
Producer
using RocketMQ.Client;
var config = new ClientConfig { Endpoints = "localhost:8081" };
// Topics are pre-warmed at create, so a topic missing on the server fails the start;
// without Topics the route is fetched on the first send.
var options = new ProducerOptions { MaxAttempts = 3 };
options.Topics.Add("TopicTest");
await using var producer = await Producer.Create(config, options);
var receipt = await producer.SendAsync(new Message("TopicTest", "hello"));
Push consumer
using System.Text;
using RocketMQ.Client;
var config = new ClientConfig { Endpoints = "localhost:8081" };
var options = new PushConsumerOptions { ConsumerGroup = "my-consumer-group" };
options.SubscriptionExpressions["TopicTest"] = FilterExpression.All;
await using var consumer = await PushConsumer.Create(config, options, view =>
{
Console.WriteLine(Encoding.UTF8.GetString(view.Body));
return ConsumeResult.Success;
});
Simple consumer
using RocketMQ.Client;
var config = new ClientConfig { Endpoints = "localhost:8081" };
var options = new SimpleConsumerOptions
{
ConsumerGroup = "my-consumer-group",
AwaitDuration = TimeSpan.FromSeconds(30),
};
options.SubscriptionExpressions["TopicTest"] = FilterExpression.All;
await using var consumer = await SimpleConsumer.Create(config, options);
while (true)
{
var messages = await consumer.ReceiveAsync("TopicTest", 16, TimeSpan.FromSeconds(15));
foreach (var message in messages)
{
await consumer.AckAsync(message);
}
}
Lite consumers
using System.Text;
using RocketMQ.Client;
var config = new ClientConfig { Endpoints = "localhost:8081" };
// One bind topic carries all lite topics; the client subscribes it with "*" unless you do.
var options = new PushConsumerOptions { ConsumerGroup = "my-lite-group" };
await using var consumer = await LitePushConsumer.Create(config, "TopicTest", options, view =>
{
Console.WriteLine($"{view.LiteTopic}: {Encoding.UTF8.GetString(view.Body)}");
return ConsumeResult.Success;
});
await consumer.SubscribeLiteAsync("order-1", OffsetOption.Min);
Publish with new Message("TopicTest", "hello") { LiteTopic = "order-1" }.
Lite consumers require the server-side lite capability: the bind topic must accept lite messages
(message.type=LITE), and the consumer group must be a lite group
(lite.bind.topic=<bind topic>).
Credentials
var config = new ClientConfig
{
Endpoints = "localhost:8081",
CredentialsProvider = new StaticCredentialsProvider(accessKey, accessSecret),
};
Delivery semantics
- Push: returning
ConsumeResult.Successacks the message. ReturningConsumeResult.Failure, or throwing from the listener, leaves it unacked; the server redelivers it after the retry policy's backoff. A FIFO message is redelivered locally, keeping its receipt handle and advancingMessageView.DeliveryAttempt; afterMaxAttemptsit is forwarded to the dead-letter queue. - Simple: a received message stays invisible for the requested duration; ack it, or extend the
duration with
ChangeInvisibleDurationAsyncbefore the receipt handle expires. - Ordering: FIFO ordering is decided by the consumer group's configuration on the server
(
isConsumeMessageOrderly), which the client reads during the settings handshake.
Compatibility
The gRPC push consumer is client-initiated long polling, not protocol-level Broker push. SQL filtering requires the target server's filtering configuration. This is an unofficial project and is not affiliated with or endorsed by the Apache Software Foundation.
License
Licensed under the Apache License 2.0.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- BouncyCastle.Cryptography (>= 2.7.0)
- Google.Protobuf (>= 3.36.2)
- Grpc.Net.Client (>= 2.85.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.14)
- System.IO.Hashing (>= 10.0.14)
-
net8.0
- BouncyCastle.Cryptography (>= 2.7.0)
- Google.Protobuf (>= 3.36.2)
- Grpc.Net.Client (>= 2.85.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.14)
- System.IO.Hashing (>= 10.0.14)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0-preview.2 | 57 | 10/30/2026 |
| 0.1.0-preview.1 | 52 | 10/30/2026 |
ICredentialsProvider is now asynchronous
New EnvironmentVariablesCredentialsProvider reads ROCKETMQ_ACCESS_KEY and ROCKETMQ_SECRET_KEY
The README language switch points at absolute urls
The samples are one project per example