如何优雅的使用RabbitMQ

DeepSeek的训练与优化流程 DeepSeek的训练体系不仅追求极致的计算效率,更注重将物理规律、人类知识、安全伦理深度融入训练过程,其"效率-安全-可解释性"三角平衡的设计理念,为行业提供了重要参考范式。 阅读详情

目录

RabbitMQ无疑是目前最流行的消息队列之一,对各种语言环境的支持也很丰富,作为一个.NET developer有必要学习和了解这一工具。消息队列的使用场景大概有3种:

1、系统集成,分布式系统的设计。各种子系统通过消息来对接,这种解决方案也逐步发展成一种架构风格,即“通过消息传递的架构”。

2、当系统中的同步处理方式严重影响了吞吐量,比如日志记录。假如需要记录系统中所有的用户行为日志,如果通过同步的方式记录日志势必会影响系统的响应速度,当我们将日志消息发送到消息队列,记录日志的子系统就会通过异步的方式去消费日志消息。

3、系统的高可用性,比如电商的秒杀场景。当某一时刻应用服务器或数据库服务器收到大量请求,将会出现系统宕机。如果能够将请求转发到消息队列,再由服务器去消费这些消息将会使得请求变得平稳,提高系统的可用性。

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

一、开始使用RabbitMQ

RabbitMQ官网提供了详细的安装步骤,另外官网还提供了RabbitMQ在六种场景的使用教程。其中教程1、3、6将覆盖99%的使用场景,所以正常来说只需要搞清楚这3个教程即可快速上手。

二、简单分析

我们以官方提供的教程1做个简单梳理:该教程展示了Producer如何向一个消息队列(message queue)发送一个消息(message),消息消费者(Consumer)收到该消息后消费该消息。

1、producer端:

 

var factory = new ConnectionFactory() { HostName = "localhost" };
 using (var connection = factory.CreateConnection())
 {
 while (Console.ReadLine() != null)
 {
 using (var channel = connection.CreateModel())
 {
 //创建一个名叫"hello"的消息队列
 channel.QueueDeclare(queue: "hello",
 durable: false,
 exclusive: false,
 autoDelete: false,
 arguments: null);
 
 var message = "Hello World!";
 var body = Encoding.UTF8.GetBytes(message);
 
 //向该消息队列发送消息message
 channel.BasicPublish(exchange: "",
 routingKey: "hello",
 basicProperties: null,
 body: body);
 Console.WriteLine(" [x] Sent {0}", message);
 }
 }
 }

该段代码非常简单,几乎到了无法精简的地步:创建了一个信道(channel)->创建一个队列->向该队列发送消息。

2、Consumer端

 

var factory = new ConnectionFactory() { HostName = "localhost" };
 using (var connection = factory.CreateConnection())
 {
 using (var channel = connection.CreateModel())
 {
 //创建一个名为"hello"的队列,防止producer端没有创建该队列
 channel.QueueDeclare(queue: "hello",
 durable: false,
 exclusive: false,
 autoDelete: false,
 arguments: null);
 
 //回调,当consumer收到消息后会执行该函数
 var consumer = new EventingBasicConsumer(channel);
 consumer.Received += (model, ea) =>
 {
 var body = ea.Body;
 var message = Encoding.UTF8.GetString(body);
 Console.WriteLine(" [x] Received {0}", message);
 };
 
 //消费队列"hello"中的消息
 channel.BasicConsume(queue: "hello",
 noAck: true,
 consumer: consumer);
 
 Console.WriteLine(" Press [enter] to exit.");
 Console.ReadLine();
 }
 }

该段代码可以理解为:创建信道->创建队列->定义回调函数->消费消息。

该实例描述了Send/Receive模式,可以简单理解为1(producer) VS 1(consumer)的场景;

如何优雅的使用RabbitMQ

 

实例3则描述了Publish/Subscriber模式,即1(producer) VS 多个(consumer);

如何优雅的使用RabbitMQ

 

在以上两个示例中,producer只需要发送消息即可,并不关心consumer的返回结果。实例6则描述了一个RPC调用场景,producer发送消息后还要接收consumer的返回结果,这一场景看起来跟使用消息队列的目的有点相悖。因为使用消息队列的目的之一就是要异步,但是这一场景似乎又将异步变成了同步,不过这一场景也很有用,比如一个用户操作产生了一个消息,应用服务收到该消息后执行了一些逻辑并使得数据库发生了变化,UI会一直等待应用服务的返回结果才刷新页面。

如何优雅的使用RabbitMQ

 

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

三、 发现抽象

我桌子上放着一本RabbitMQ in Action,另外官网提供的文档也很详细,我感觉在一个月内我就能精通RabbitMQ,到时候简历上又可以写上“精通…”,感觉有点小得意呢... ,但是我知道这并不是使用RabbitMQ的最佳方式。

我们知道合理的抽象可以帮我们隐藏掉一些技术细节,让我们将重心放在核心业务上,比如一个人问你:“大雁塔如何走?”你的回答可能是“小寨往东,一直走两站,右手边”,如果你回答:“右转45度,向前走100米,再转90度…”,对方就会迷失在这些细节中。

消息队列的使用过程中实际隐藏着一种抽象——服务总线(Service Bus)。

我们在回头看第一个例子,这个例子隐含的业务是:ClientA发送一个指令,ClientB收到该指令后做出反应。如果是这样,我们为什么要关心如何创建channel,如何创建一个queue? 我仅仅是要发送一个消息而已。另外这个例子写的其实不够健壮:

没有重试机制:如果ClientB第一次没有执行成功如何对该消息处理?

没有错误处理机制:如果ClientB在重试了N次之后还是异常如何处理该消息?

没有熔断机制;

如何对ClientA做一个schedule(计划安排),比如定时发送等;

没有消息审计机制;

无法对消息的各个状态做追踪;

事物处理等。

服务总线正是这种场景的抽象,并且为我们提供了这些机制,让我们赶快来看个究竟吧。

四、初识MassTransit

MassTransit是.NET平台下的一款开源免费的ESB产品,官网:http://masstransit-project.com/,GitHub 700 star,500 Fork,类似的产品还有NServiceBus,之所以要选用MassTransit是因为他要比NServiceBus轻量级,另外在MassTransit开发之初就选用了RabbitMQ作为消息传输组建;同时我想拿他跟NServiceBus做个比较,看看他们到底有哪些侧重点。

1、新建控制台应用程序:Masstransit.RabbitMQ.GreetingClient

使用MassTransit可以从Nuget中安装:

Install-Package MassTransit.RabbitMQ

2、创建服务总线,发送一个命令

static void Main(string[] args)
{
 Console.WriteLine("Press 'Enter' to send a message.To exit, Ctrl + C");
 
 var bus = BusCreator.CreateBus();
 var sendToUri = new Uri($"{RabbitMqConstants.RabbitMqUri}{RabbitMqConstants.GreetingQueue}");
 
 while (Console.ReadLine()!=null)
 {
 Task.Run(() => SendCommand(bus, sendToUri)).Wait();
 }
 
 Console.ReadLine();
}
 
private static async void SendCommand(IBusControl bus,Uri sendToUri)
{
 var endPoint =await bus.GetSendEndpoint(sendToUri);
 var command = new GreetingCommand()
 {
 Id = Guid.NewGuid(),
 DateTime = DateTime.Now
 };
 
 await endPoint.Send(command);
 
 Console.WriteLine($"send command:id={command.Id},{command.DateTime}"); 
}

这一段代码隐藏了众多关于消息队列的细节,将我们的注意力集中在发送消息上,同时ServiceBus提供的API也更接近业务,我们虽然发送的是一个消息,但是在这种场景下体现出来是一个命令,Send(command)这一API描述了我们的意图。

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

3、服务端接收这一命令

新建一个命令台控制程序:Masstransit.RabbitMQ.GreetingServer

 

var bus = BusCreator.CreateBus((cfg, host) =>
{
 cfg.ReceiveEndpoint(host, RabbitMqConstants.GreetingQueue, e =>
 {
 e.Consumer<GreetingConsumer>();
 
 });
});

这一代码可以理解为服务端在监听消息,我们在服务端注册了一个名为“GreetingConsumer”的消费者,GreetingConsumer的定义:

 

public class GreetingConsumer :IConsumer<GreetingCommand>
{
 public async Task Consume(ConsumeContext<GreetingCommand> context)
 {
 
 await Console.Out.WriteLineAsync($"receive greeting commmand: {context.Message.Id},{context.Message.DateTime}");
 }
}

该consumer可以消费类型为GreetingCommand的消息。这一实例几乎隐藏了有关RabbitMQ的技术细节,将代码中心放在了业务中,将这两个控制台应用跑起来试试:

如何优雅的使用RabbitMQ

 

五、实现Publish/Subscribe模式

发布/订阅模式使得基于消息传递的软件架构成为可能,这一能力表现为ClientA发送消息X,ClientB和ClientC都可以订阅消息X。

1、我们在上面的例子中改造一下,当GreetingConsumer收到GreetingCommand后发送一个GreetingEvent:

 

var greetingEvent = new GreetingEvent()
 {
 Id = context.Message.Id,
 DateTime = DateTime.Now
 };
 
 await context.Publish(greetingEvent);

2、新建控制台程序Masstransit.RabbitMQ.GreetingEvent.SubscriberA用来订阅GreetingEvent消息:

 

var bus = BusCreator.CreateBus((cfg, host) =>
 {
 cfg.ReceiveEndpoint(host, RabbitMqConstants.GreetingEventSubscriberAQueue, e =>
 {
 e.Consumer<GreetingEventConsumer>();
 });
 });
 
 bus.Start();

定义GreetingEventConsumer:

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

public class GreetingEventConsumer:IConsumer<Greeting.Message.GreetingEvent>
 {
 public async Task Consume(ConsumeContext<Greeting.Message.GreetingEvent> context)
 {
 await Console.Out.WriteLineAsync($"receive greeting event: id {context.Message.Id}");
 }
 }

这一代码跟Masstransit.RabbitMQ.GreetingServer接受一个命令几乎一模一样,唯一的区别在于:

在Send/Receive模式中Client首先要获得对方(Server)的终结点(endpoint),直接向该终结点发送命令。Server方监听自己的终结点并消费命令。

而Publish/Subscribe模式中Client publish一个事件,SubscriberA在自己的终结点(endpointA)监听事件,SubscriberB在自己的终结点(endpointB)监听事件。

3、根据上面的分析再定义一个Masstransit.RabbitMQ.GreetingEvent.SubscriberB

4、将4个控制台应用程序跑起来看看

如何优雅的使用RabbitMQ

 

六、实现RPC模式

这一模式在Masstransit中被称作Request/Response模式,通过IRequestClient<IRequest, IResponse> 接口来实现相关操作。一个相关的例子在官方的github。

结束语:本篇文章分析了如何使用Masstransit来抽象业务,避免直接使用具体的消息队列,当然本文提到的众多服务总线机制,如“重试、熔断等”并没有在该文中出现,需要大家进一步去了解该项目。

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

通过对Masstransit的一些试用和NServiceBus的对比,Masstransit在实际项目中很容易上手并且免费,各种API定义的也非常清晰,但是官方的文档有点过于简单,实际使用中还需要去做深入的研究。作为.NET平台下为数不多的ESB开源产品,其关注程度还是不够,期待大家为开源项目做出贡献。

实验手册(灾难恢复) 我们发现DC1与DC2的复制出现问题,此时我们检查了在DC2中,DC1是否被正确注册。这里选择还原系统状态,因为我们原DC1上只备份了AD的数据,所以我们在新的这台服务器上还原的也是AD数据库。因为我们是单域下的测试,只测试了一个域,所以它会出现这样的报错。我们选择远程共享文件夹,我们备份的时候,是在备份这台服务器上的。同时删除SRV记录,A记录,NS记录,SOA记录,框框里面的所有有关dc1的记录全部删除。如果在企业中AD数据的备份是每周或者每月都会有一次备份,选择恢复AD数据库的时间。 阅读详情

相关推荐

EMQX 结合MySQL实现精细化ACL权限管理实战

本文详细介绍了如何通过EMQX结合MySQL实现精细化的ACL权限管理,提升物联网设备接入和消息传输的安全性。内容包括环境准备、基础配置、权限规则设计技巧以及高级应用与性能优化方案,帮助开发者快速掌握动态生效、便于管理的权限控制方法。

weixin_28683689的博客 199

MassTransit是什么?

MassTransit是一个用于.NET的开源分布式应用程序框架,主要用于构建基于消息、异步和事件驱动模式的系统。它旨在简化依赖于消息模式的应用程序的开发,包括发布-订阅、请求-响应和消息路由等模式。MassTransit提供了工具,用于实现跨多个消息交互跨足的长时间运行过程,称为saga,从而使您可以建模复杂的业务流程。MassTransit是.NET生态系统中构建分布式系统的热门选择之一,因为它抽象了消息基础设施的复杂性,并提供了高级别的、开发人员友好的API。

极客神殿 1926

变邻域搜索(VNS)原理梳理和应用细节-附求解VRPTW问题C++代码

文章目录1、简介-introduction2、VNS的基本机制2.1 变邻域下降方法-Variable Neighborhood Descent2.2基本变邻域搜索方法-Basic Variable Neighborhood Search2.3 终止准则3、VNS的拓展和混杂算法3.1 VNS的拓展3.2 变邻域分解搜索-Variable Neighborhood Decomposition Search3.3 偏变邻域搜索-Skewed VNS3.4 并行变邻域搜索-Parallel VNS4、VNS和其

dragon Fly的博客 6827

MassTransit | .NET 分布式应用框架

引言❝A free, open-source distributed application framework for .NET. 一个免费、开源的.NET 分布式应用框架。 -- MassTransit 官网❞MassTransit[1],直译公共交通, 是由Chris Patterson开发的基于消息驱动的.NET 分布式应用框架,其核心思想是借助消息来实现服务之间的松耦合异步通信,进而确...

圣杰 767

Linux下搭建J-Link调试环境:OpenOCD+GDB实战指南

嵌入式开发中,调试器是连接开发主机与目标硬件的关键桥梁,其核心原理是通过标准协议(如JTAG/SWD)访问芯片内部的调试模块。GDB作为通用的调试客户端,通过远程协议与调试服务器通信,而OpenOCD则扮演了协议转换与硬件驱动的角色,实现了调试命令的翻译与执行。这种开源工具链的组合,为开发者提供了高度的定制化与自动化能力,尤其适合需要与持续集成流程深度结合的复杂项目。在实际应用中,针对特定芯片(如ARM7TDMI)进行正确的内存控制器与时钟初始化是成功调试的前提,这常常涉及对板级支持包的深入理解。本文以S3

weixin_29889665的博客 333

告别游戏卡关!用Cheat Engine 7.5修改单机游戏数据的保姆级教程(附Tutorial靶场练习)

本文提供了一份详细的Cheat Engine 7.5使用教程,帮助玩家轻松修改单机游戏数据。从基础操作到高级技巧,包括精确值扫描、模糊扫描、指针扫描和代码注入,教程还涵盖了《植物大战僵尸》和《星露谷物语》的实战案例,确保玩家能够安全、高效地优化游戏体验。

weixin_30082367的博客 790

MassTransit一个优秀的.NET消息(事件)总线框架

1 前置阅读 在阅读本文章之前,你可以先阅读: RabbitMQ入门 什么是观察者模式 什么是事件总线 如何使用RabbitMQ实现事件总线 2 简介 MassTransit 是一个自由、开源、轻量级的消息总线, 用于使用. NET 框架创建分布式应用程序。MassTransit 在现有消息传输上提供了一组广泛的功能, 从而使开发人员能够友好地使用基于消息的会话模式异步连接服务。基于消息的通信是实现面向服务的体系结构的可靠和可扩展的方式。 3 使用 首先,将MassTransit的NuGet软件包安装到

极客神殿 3391

《测控仪器设计课后习题答案-浦昭邦-王宝光

《测控仪器设计课后习题答案-浦昭邦-王宝光 1.1. 测控仪器的概念是什么? 测控仪器则是利用测量和控制的理论,采用机、电、光各种计量测试原理及控制系统与计算机相结合的一种范围广泛的测量仪器。 1.2. 为什么说测控仪器的发展与科学技术发展密切相关? 仪器仪表的用途和重要性— 遍及国民经济各个部门,深入到人民生活的各个角落,仪器仪表中的计量测试仪器与控制仪器统称为测控仪器,可以说测控仪器的水平是科学技术现代化的重要标志。 仪器仪表的用途: 在机械制造业中:对产品的静态与动态性能测试;加工过程的控制与监测;设

无名何许人的博客 2978

MassTransit-概念-04生产者

应用程序或服务可以使用两种不同的方法生成消息。消息可以被发送或发布。每种方法的行为非常不同,但通过查看每种方法涉及的消息类型很容易理解。当消息被发送时,它使用被传递到特定端点,例如队列。当消息被发布时,它不会被发送到特定端点,而是广播给任何订阅了该消息类型的消费者。对于这两种不同的行为,我们将发送的消息描述为命令,将发布的消息描述为事件。有关消息名称的更多信息,请参阅消息概念页面。

NuClear的.Net专栏 1850

CUDA:实现使用cuSolverSP底层API实现Cholesky因式分解(附完整源码)

CUDA:实现使用cuSolverSP底层API实现Cholesky因式分解(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 350

05 - matlab m_map地学绘图工具基础函数 - 设置比例尺指北针

本篇介绍下m_map中添加指北针(m_northarrow)、比例尺(m_ruler)和进行比例缩放(m_scale)的函数及其用法 。提供了 示例以便参考,罗列了 各函数可设属性。希望对绘图的你有所帮助。

weixin_43339605的博客 1948

rabbitmq怎么停止_如何让rabbitmq消费者优雅的关闭(golang版本)

阅读本文需要掌握的知识:1、rabbit mq2、golang如果项目使用消息队列进行异步处理,大家应该都会碰上一个问题:如果某个消息正在处理中,这时候中断程序(或者更新),那么将会出现数据异常。这种情况可以通过两种方式解决该问题:1、使用自带的ack机制,将在消息处理完之后,发送ack消息给mq,这样如果处理到一半,程序中断,mq会将该消息发送给其他消费者进行处理。但是该解决方案会产生另一个问题...

weixin_39689394的博客 5044

Unreal5 从入门到精通之 学习Niagara特效系统

UE5 Niagara粒子系统解析 Niagara是UE5中的高性能粒子特效系统,相比传统粒子系统具有完全可编程性和可视化节点编辑两大特点。核心单元发射器(Emitter)分为模板发射器(预设效果如喷泉、火焰)和空白发射器(高度自定义)。系统提供13种预设模板,包括吹飞粒子、五彩纸屑爆发、动态光束等常见特效。 Niagara采用三级模块化设计: 系统级:全局参数设置与更新 发射器级:控制粒子生成规则与行为 粒子级:处理单个粒子的生命周期和渲染 关键模块包括初始化粒子属性、物理模拟、颜色渐变等,支持GPU加速

TxNet 1129

【RabbitMQ】java代码中优雅实现方案

在Java中创建交换机和队列有两种主要方式。第一种是基于Bean的手动创建,生产者负责发送消息,消费者则声明队列、交换机及绑定关系,并接收消息。这种方式适用于多个队列绑定到同一交换机的情况。然而,这种方式存在流程繁杂的问题,每次绑定不同的key都需要另写一个Bean。因此,更推荐第二种方式,即基于注解声明队列和交换机。这种方式更为优雅,简化了绑定流程,提高了代码的可读性和维护性。通过注解,可以更灵活地管理队列和交换机的绑定关系,减少重复代码,提升开发效率。

m0_74289770的博客 595

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

rabbitmq 消费端如何优雅的关闭

rabbimq 消费者如何优雅的关闭

qustern的博客 2254

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

从阻塞到异步:Go语言优雅集成RabbitMQ的实战指南

Go语言(The Go programming language)凭借其简洁高效的并发模型,成为构建高性能消息系统的理想选择。本文将带你探索如何在Go项目中从零开始集成RabbitMQ,通过实战案例掌握从基础阻塞调用到高级异步处理的全流程,让你的消息通信架构更具弹性与可扩展性。 ## 一、环境准备:快速搭建Go与RabbitMQ开发环境 ### 1.1 安装Go语言环境 确保你的开发环境已安装

gitblog_00928的博客 476

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

SpingBoot之优雅的对接RabbitMQ

1、加入依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-stream-rabbit</artifactId> </dependency> 2、发布消息 @Au...

小达哥的博客 633

如何高效优雅的使用RabbitMQ

RabbitMQ无疑是目前最流行的消息队列之一,对各种语言环境的支持也很丰富,作为一个.NET developer有必要学习和了解这一工具。

xiaocai 551
上一篇: 分布式系统关注点——99%的人都能看懂的「熔断」以及最佳实践
下一篇: 日志打入kafka改造历程-我们到底能走多远系列
javaQQ群 866865133
博客等级 码龄8年 59粉丝 309原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值