net core3.1使用RocketMQ
工具:
vs2019 netcore3.1 阿里云RocketMQ V1.0.1
参考:阿里云官方示例:https://github.com/aliyunmq/mq-http-csharp-sdk
RocketMQ 是什么
Github 上关于 RocketMQ 的介绍:
RcoketMQ 是一款低延迟、高可靠、可伸缩、易于使用的消息中间件。具有以下特性:
- 支持发布/订阅(Pub/Sub)和点对点(P2P)消息模型
- 在一个队列中可靠的先进先出(FIFO)和严格的顺序传递
- 支持拉(pull)和推(push)两种消息模式
- 单一队列百万消息的堆积能力
- 支持多种消息协议,如 JMS、MQTT 等
- 分布式高可用的部署架构,满足至少一次消息传递语义
- 提供 docker 镜像用于隔离测试和云集群部署
- 提供配置、指标和监控等功能丰富的 Dashboard
专业术语
Producer
消息生产者,生产者的作用就是将消息发送到 MQ,生产者本身既可以产生消息,如读取文本信息等。也可以对外提供接口,由外部应用来调用接口,再由生产者将收到的消息发送到 MQ。
Producer Group
生产者组,简单来说就是多个发送同一类消息的生产者称之为一个生产者组。在这里可以不用关心,只要知道有这么一个概念即可。
Consumer
消息消费者,简单来说,消费 MQ 上的消息的应用程序就是消费者,至于消息是否进行逻辑处理,还是直接存储到数据库等取决于业务需要。
Consumer Group
消费者组,和生产者类似,消费同一类消息的多个 consumer 实例组成一个消费者组。
Topic
Topic 是一种消息的逻辑分类,比如说你有订单类的消息,也有库存类的消息,那么就需要进行分类,一个是订单 Topic 存放订单相关的消息,一个是库存 Topic 存储库存相关的消息。
Message
Message 是消息的载体。一个 Message 必须指定 topic,相当于寄信的地址。Message 还有一个可选的 tag 设置,以便消费端可以基于 tag 进行过滤消息。也可以添加额外的键值对,例如你需要一个业务 key 来查找 broker 上的消息,方便在开发过程中诊断问题。
Tag
标签可以被认为是对 Topic 进一步细化。一般在相同业务模块中通过引入标签来标记不同用途的消息。
Broker
Broker 是 RocketMQ 系统的主要角色,其实就是前面一直说的 MQ。Broker 接收来自生产者的消息,储存以及为消费者拉取消息的请求做好准备。
Name Server
Name Server 为 producer 和 consumer 提供路由信息。
第一步:阿里云创建实例
创建完实例后,可以得到我们需要的下面这些参数值。
// 设置HTTP接入域名(此处以公共云生产环境为例) private const string _endpoint = "${HTTP_ENDPOINT}"; // AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建 private const string _accessKeyId = "${ACCESS_KEY}"; // SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建 private const string _secretAccessKey = "${SECRET_KEY}"; // 所属的 Topic private const string _topicName = "${TOPIC}"; // Topic所属实例ID,默认实例为空 private const string _instanceId = "${INSTANCE_ID}"; // 您在控制台创建的 Consumer ID(Group ID) private const string _groupId = "${GROUP_ID}";
第二步:引用RocketMQ

第三步:创建消息生产类:

using System; using System.Collections.Generic; using System.Threading; using Aliyun.MQ.Model; using Aliyun.MQ.Model.Exp; using Aliyun.MQ.Util; namespace Aliyun.MQ.Sample { public class ProducerSample { // 设置HTTP接入域名(此处以公共云生产环境为例) private const string _endpoint = "${HTTP_ENDPOINT}"; // AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建 private const string _accessKeyId = "${ACCESS_KEY}"; // SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建 private const string _secretAccessKey = "${SECRET_KEY}"; // 所属的 Topic private const string _topicName = "${TOPIC}"; // Topic所属实例ID,默认实例为空 private const string _instanceId = "${INSTANCE_ID}"; private static MQClient _client = new Aliyun.MQ.MQClient(_accessKeyId, _secretAccessKey, _endpoint); static MQProducer producer = _client.GetProducer(_instanceId, _topicName); static void Main(string[] args) { try { // 循环发送4条消息 for (int i = 0; i < 4; i++) { TopicMessage sendMsg; if (i % 2 == 0) { sendMsg = new TopicMessage("dfadfadfadf"); // 设置属性 sendMsg.PutProperty("a", i.ToString()); // 设置KEY sendMsg.MessageKey = "MessageKey"; } else { sendMsg = new TopicMessage("dfadfadfadf", "tag"); // 设置属性 sendMsg.PutProperty("a", i.ToString()); // 定时消息, 定时时间为10s后 sendMsg.StartDeliverTime = AliyunSDKUtils.GetNowTimeStamp() + 10 * 1000; } TopicMessage result = producer.PublishMessage(sendMsg); Console.WriteLine("publis message success:" + result); } } catch (Exception ex) { Console.Write(ex); } } } }
第四步,创建消息消费者类

using System; using System.Collections.Generic; using System.Threading; using Aliyun.MQ.Model; using Aliyun.MQ.Model.Exp; using Aliyun.MQ; namespace Aliyun.MQ.Sample { public class ConsumerSample { // 设置HTTP接入域名(此处以公共云生产环境为例) private const string _endpoint = "${HTTP_ENDPOINT}"; // AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建 private const string _accessKeyId = "${ACCESS_KEY}"; // SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建 private const string _secretAccessKey = "${SECRET_KEY}"; // 所属的 Topic private const string _topicName = "${TOPIC}"; // Topic所属实例ID,默认实例为空 private const string _instanceId = "${INSTANCE_ID}"; // 您在控制台创建的 Consumer ID(Group ID) private const string _groupId = "${GROUP_ID}"; private static MQClient _client = new Aliyun.MQ.MQClient(_accessKeyId, _secretAccessKey, _endpoint); static MQConsumer consumer = _client.GetConsumer(_instanceId, _topicName, _groupId, null); static void Main(string[] args) { // 在当前线程循环消费消息,建议是多开个几个线程并发消费消息 while (true) { try { // 长轮询消费消息 // 长轮询表示如果topic没有消息则请求会在服务端挂住3s,3s内如果有消息可以消费则立即返回 List<Message> messages = null; try { messages = consumer.ConsumeMessage( 3, // 一次最多消费3条(最多可设置为16条) 3 // 长轮询时间3秒(最多可设置为30秒) ); } catch (Exception exp1) { if (exp1 is MessageNotExistException) { Console.WriteLine(Thread.CurrentThread.Name + " No new message, " + ((MessageNotExistException)exp1).RequestId); continue; } Console.WriteLine(exp1); Thread.Sleep(2000); } if (messages == null) { continue; } List<string> handlers = new List<string>(); Console.WriteLine(Thread.CurrentThread.Name + " Receive Messages:"); // 处理业务逻辑 foreach (Message message in messages) { Console.WriteLine(message); Console.WriteLine("Property a is:" + message.GetProperty("a")); handlers.Add(message.ReceiptHandle); } // Message.nextConsumeTime前若不确认消息消费成功,则消息会重复消费 // 消息句柄有时间戳,同一条消息每次消费拿到的都不一样 try { consumer.AckMessage(handlers); Console.WriteLine("Ack message success:"); foreach (string handle in handlers) { Console.Write("\t" + handle); } Console.WriteLine(); } catch (Exception exp2) { // 某些消息的句柄可能超时了会导致确认不成功 if (exp2 is AckMessageException) { AckMessageException ackExp = (AckMessageException)exp2; Console.WriteLine("Ack message fail, RequestId:" + ackExp.RequestId); foreach (AckMessageErrorItem errorItem in ackExp.ErrorItems) { Console.WriteLine("\tErrorHandle:" + errorItem.ReceiptHandle + ",ErrorCode:" + errorItem.ErrorCode + ",ErrorMsg:" + errorItem.ErrorMessage); } } } } catch (Exception ex) { Console.WriteLine(ex); Thread.Sleep(2000); } } } } }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)