.Net CoreRabbitMQ消息存储可靠机制(下)

前言

上篇讨论过消息投递和消息消费过程中如何确保可靠传输,也提及到消息到达RabbitMQ中到被消费前也需要可靠的留存,可因许多的不确定因素会影响着消息的存在与否。

消息中转点

生产者发送消息到RabbitMQ中,如果交换机根据自身类型和RoutingKey能够匹配到队列,则存入相关队列,但当匹配不到队列时,遇到两种情况而使得消息走向不同的方向,消息可能会丢失或是发回给生产者,这取决于生产者对消息的配置。

984a3078e93613b7f64d19e5eb713eb0.png

  • 生产者设置了Mandatory且为true,则消息回退给生产者。

  • 当生产者为设置Mandatory或是设置为false时,为了避免消息丢失,可以由交换机路由给备份交换机负责去搞定存储。
    6e3540ba688da5fd695466a78f1d0d8f.png

Mandatory

生产者发送消息时,可以设置一个参数mandatory,来决定消息到达RabbitMQ后,如果出现交换机根据自身类型及RoutingKey找不到合适的队列情况下,消息的一个走向。

  • 当mandatory为true时,消息则返回给生产者。
    deac306a745d305f2783c354eb6af32b.png

  • 当mandatory为false时,消息则被丢弃。

生产者代码

当在BasicPublish方法参数中设置mandatory为true且队列暂不声明时,仅有一个交换机,消息将会被返回。

var connFactory = new ConnectionFactory
{HostName = "xxx.xxx.xxx.xxx",Port = 5672,UserName = "rabbitmqdemo",Password = "rabbitmqdemo@test",VirtualHost = "rabbitmqdemo"};
using (var conn = connFactory.CreateConnection())
{using (var channel = conn.CreateModel()){var exchangeName = "mandatory_publishsubscribe_exchange";channel.ExchangeDeclare(exchange: exchangeName, type: "fanout");while (true){Console.WriteLine("消息内容(exit退出):");var message = Console.ReadLine();if (message.Trim().ToLower() == "exit"){break;}var body = Encoding.UTF8.GetBytes(message);channel.BasicPublish(exchange: exchangeName, routingKey: "", mandatory: true, basicProperties: null, body: body);Console.WriteLine("消息内容发送完毕:" + message);}}
}

生产者发送消息,交换机收到消息但无对应队列,消息被返回。
1682330050e1b0112a61e337c50d13fb.png

为了直观的知道消息返回到了生产者,我们可以增加一个监听器,来监听返回的消息。

监听回退消息

当mandatory设置为true,消息回退时可以监听消息

channel.BasicReturn += new EventHandler<RabbitMQ.Client.Events.BasicReturnEventArgs>((sender, e) =>
{var message = Encoding.UTF8.GetString(e.Body.ToArray());Console.WriteLine($"收到回退消息:{message}");
});

生产者发送消息,因无匹配队列,消息被返回,可以直观的看到返回的消息。
d51a69344d3355d0e74360d5152fd52c.png

备份交换机

当mandatory设置为false时,消息被丢失了,这种情况可不太好。可以使用备份交换机来存储原要被丢弃的消息,当需要这些消息的时候,还能拿到这些消息。实际上备份交换机没有什么特殊,和主交换机是一样的只是充当备份的角色。
28f96c2a338a6e9daeb0a62a15350d5a.png

生产者代码

  1. 在创建主交换机的时候,给定参数argument,设置该主交换机的备份交换机,指定备份交换机名称。

  2. 然后声明备份交换机并绑定一个队列,用于存储被丢弃的消息。

  3. 发送消息时mandatory参数设置为false。

var connFactory = new ConnectionFactory
{HostName = "xxx.xxx.xxx.xxx",Port = 5672,UserName = "rabbitmqdemo",Password = "rabbitmqdemo@test",VirtualHost = "rabbitmqdemo"};
using (var conn = connFactory.CreateConnection())
{using (var channel = conn.CreateModel()){var exchangeName = "aedemo_publishsubscribe_exchange";var alternateExchangeName = "aedemo_ae_publishsubscribe_exchange";var arguments = new Dictionary<string, object>{{ "alternate-exchange", alternateExchangeName }};channel.ExchangeDeclare(exchange: exchangeName, type: "fanout", arguments: arguments);channel.ExchangeDeclare(exchange: alternateExchangeName, type: "fanout");var alternateExchangeQueueName = alternateExchangeName + "_worker";channel.QueueDeclare(queue: alternateExchangeQueueName, durable: false, exclusive: false, autoDelete: false, arguments: null);channel.QueueBind(queue: alternateExchangeQueueName, exchange: alternateExchangeName, routingKey: "");while (true){Console.WriteLine("消息内容(exit退出):");var message = Console.ReadLine();if (message.Trim().ToLower() == "exit"){break;}var body = Encoding.UTF8.GetBytes(message);channel.BasicPublish(exchange: exchangeName, routingKey: "", mandatory: false, basicProperties: null, body: body);Console.WriteLine("消息内容发送完毕:" + message);}}
}

启动程序,可以从Web面板中看到主交换机和备份交换机都创建完毕,并且主交换机打上了有AE的标记。
6f3b310dd3491190e77c6117e0f71cba.png

生产者发送消息,经主交换机匹配但无合适队列后,转发给备份交换机,路由到其队列存储。
5d6456ab7aa6c3e556c355ed04ddd838.png

注:推荐使用Fanout类型的交换机,如果其他比如Direct,当主交换机转发到备份交换机,在进行匹配时候,如果消息给定的RoutingKey没有匹配到相应的队列,消息则会被丢失,这样一来,最初的预想就出现偏差了。

持久化

当RabbitMQ在异常情况下,比如系统宕机、重启、关闭等,可能会导致数据丢失,可靠性降低。针对这种情况,RabbitMQ提供了持久化机制,将消息本身和元数据(队列、交换机、绑定信息)都保存到磁盘中。具体分为三类持久化

  • 交换机持久化

  • 队列持久化

  • 消息持久化

交换机持久化

当RabbitMQ遇到异常情况(如服务重启)后,如果没有设置交换机持久化,那么交换机相关数据则会被丢失,生产者再发送消息到指定交换机时就失败了。

服务重启异常

1、在Web中新建一个交换机,指定非持久化模式。
34daa386937e9097f9404a5351520260.png

2、新建一个队列,指定非持久化模式。
4b2371d59c5a5690f4a4bb0396382618.png

3、设置交换机和队列的绑定关系。
bb66b7d3277a56204c963576b3963d32.png

4、生产者前部分正常发送消息,中间经服务重启后,交换机、队列及绑定关系都被清除,生产继续发送消息,出现异常。
55b4300e186372cdd0bd3bdcb8c0667c.png

持久化设置

在声明交换机时可以指定durable参数设置为true(Web面板中也可设置)。

channel.ExchangeDeclare(exchange: exchangeName, type: "fanout", durable: true, arguments: null);

RabbitMQ服务重启,生产者继续发送消息给交换机。
425b7078bc22b9f20fe1de881c0b13d3.png

队列持久化

队列的持久化是队列声明时设置durable参数为true,如果队列不持久化,异常情况(如服务重启)后,队列元数据丢失,存储在内的消息也就丢失了。

服务重启异常

1、Web中创建一个交换机并设置为持久化模式。
578be77df85002537a2ebe56e9cd6b7b.png

2、创建一个队列并设置为非持久化模式
c41a314caf79b94557960a310f6a3725.png

3、设置交换机和队列的绑定关系。
e4a74d34c89c9ef201502a2cb3311c5e.png

4、生产者前部分正常发送消息,中间经服务重启后,队列及绑定关系被清除,生产继续发送消息,匹配队列失败,消息被回退给生产者。
cd86e51deabf7a1059c187c402885d2c.png

持久化设置

在声明队列时可以指定durable参数设置为true(Web面板中也可设置)。

channel.QueueDeclare(queue: queueName, durable: true, exclusive: false, autoDelete: false, arguments: null);

RabbitMQ服务重启,生产者继续发送消息给交换机。
8cbd37b4451083293017aa2fe199c547.png

消息持久化

队列的持久化仅能保证其自身的数据不丢失,而其存储的消息却不能保证不会丢失。
a4208745ccb8466d13827ad732fa2159.png

持久化设置

需要对消息消息设置持久化,以确保消息本身不会因异常情况(如服务重启)而丢失。在发送消息时,可以设置消息的基础属性,来支持消息的持久化。

var basicProperties = channel.CreateBasicProperties();
basicProperties.DeliveryMode = 2;// 1非持久化 2持久化channel.BasicPublish(exchange: exchangeName, routingKey: "", mandatory: true, basicProperties: basicProperties, body: body);

如此一来,当异常情况(如服务重启后),消息还是存在的。
0ff99a92269d39cadaf41c5ae733a31a.png

注:消息持久化会影响性能,仅确保有价值的消息持久化,来权衡可靠与吞吐量。

2022-08-25,望技术有成后能回来看见自己的脚步

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283084.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nginx安装及负载均衡配置

Nginx (“engine x”) 是一个高性能的 HTTP 和 反向代理 服务器&#xff0c;也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的&#xff0c;第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发…

智能停车O2O 独角兽初现:“ETCP停车”获5000万美金A轮融资

日前&#xff0c;国内第一智能停车平台“ETCP停车”宣布完毕A轮融资&#xff0c;由源代码资本、SIG、易车网、经纬中国和商企界知名人士联合投资超过5000万美金。同一时候获悉&#xff0c;ETCP作为中国智能停车行业龙头老大&#xff0c;不仅是该行业的创建者和领军品牌&#xf…

ASP.NET MVC使用Bootstrap系统(2)——使用Bootstrap CSS和HTML元素

阅读目录 Bootstrap 栅格&#xff08;Grid&#xff09;系统Bootstrap HTML元素Bootstrap 验证样式ASP.NET MVC创建包含Bootstrap样式编辑模板小结Bootstrap提供了一套丰富CSS设置、HTML元素以及高级的栅格系统来帮助开发人员快速布局网页。所有的CSS样式和HTML元素与移动设备优…

VS2017调试闪退之Chrome

原文:VS2017调试闪退之Chrome巨硬build后发了15.7.1满载期待的升级了。。结果NM泪奔................... 为啥 泪奔&#xff1f; 使用Chrome 调试闪退&#xff0c;MMP ,一想肯定是VS的锅咯&#xff0c;各种抓头发。。 试试看看VS配置发现 &#xff0c;多了点东西。。 都勾上后&…

ios UISearchBar搜索框的基本使用

摘要: 小巧简洁的原生搜索框&#xff0c;漂亮而易用&#xff0c;如果我们的应用没有特殊需求&#xff0c;都可以使用它。iOS中UISearchBar(搜索框)使用总结 初始化&#xff1a;UISearchBar继承于UIView&#xff0c;我们可以像创建View那样创建searchBar UISearchBar * bar [[U…

Win8下怎样安装Win7 or Win7下怎样安装win8?

预计非常多人可能会用U盘安装工具去去做双系统的安装&#xff08;Win8下安装Win7&#xff0c; Win7下安装Win8&#xff09;。可是在安装过程中你 会发现一个问题&#xff1a;win7下安装win8&#xff0c;提示你mbr硬盘格式不能安装win8&#xff1b;win8下安装win7&#xff0c;提…

Linux 练习题-3文件与磁盘 问答

1、描述Liux下软链接和硬链接的区别创建命令不同&#xff0c;ln 命令创建硬链接&#xff0c;ln -s 创建软链接inode节点号不同&#xff0c;硬链接inode与源文件相同&#xff0c;软链接inode与源文件不同使用对象不同&#xff0c;硬链接只能对文件使用&#xff0c;软链接可以对文…

.NET Offer 快到碗里来!.NET 招聘季

关注我们谈到 .NET 在中国的推广和发展&#xff0c;.NET 开发者求职就业及 .NET 企业招人用人的问题往往常被提及。初学者会担心学习 .NET 之后的就业问题&#xff0c;.NET 开发者在求职过程中没有足够多的渠道来获取 .NET 招聘信息&#xff0c;而与此同时&#xff0c;采用 .NE…

java的collections_Java中Collection和Collections的区别

1) 排序(Sort)使用sort方法可以根据元素的自然顺序 对指定列表按升序进行排序。列表中的所有元素都必须实现 Comparable 接口。此列表内的所有元素都必须是使用指定比较器可相互比较的1 List list new ArrayList();2 int array[] {112, 111, 23, 456, 231};3 for (int i 0; …

jQuery事件绑定(一)

2019独角兽企业重金招聘Python工程师标准>>> 一、on方法 在Jquery1.7中添加&#xff0c;用来代替其他事件绑定方法。向匹配元素添加一个或多个事件处理程序 使用语法&#xff1a; $(selector).on(event,childselector,data,function) 参数&#xff1a; event&#x…

JDBC学习笔记之JDBC简介

1. 引言 JDBC API是一种Java API&#xff0c;可以访问任何类型的表格数据&#xff0c;特别是存储在关系数据库中的数据。 JDBC可以帮助我们编写下列三种编程活动的java应用程序&#xff1a; 1.连接到数据源&#xff0c;如数据库;2.发送查询和更新语句到数据库;3.检索并处理从数…

PaddleOCR在 windows下的webAPI部署方案

很多小伙伴在使用OCR时都希望能过采用API的方式调用&#xff0c;这样就可以跨端跨平台了。本文将介绍一种基于python的PaddleOCR识方案。喜欢的可以关注公众号&#xff0c;获取更多内容。# 一、 windows环境下部署###1.环境操作系统&#xff1a;windows10&#xff1b;主要软件环…

Vim的NerdTree插件

一个项目文件多起来时&#xff0c;左边的文件树菜单是必要的。参考&#xff1a;常用文件树快捷键所有命令及推荐键盘映射&#xff1a;官方 在vundle插件管理的方式&#xff0c;直接在~/.vimrc中的Plugin段落中加入Plugin "scrooloose/nerdtree"然后重启Vim并输入Plug…

java简单投票系统_JSP实现的简单Web投票程序代码

本文实例讲述了JSP实现的简单Web投票程序。分享给大家供大家参考。具体如下&#xff1a;这里使用文本文件作为数据存储的投票系统。1. vote.java&#xff1a;package vote;import java.io.*;import java.util.*;public class vote {public String filePath "";publi…

HTTP2指纹识别(一种相对不为人知的网络指纹识别方法)

这是关于网络指纹识别的两部分系列的第二部分上一部分我介绍了有关TLS 指纹识别方法&#xff08;以及在不同客户端的指纹有何区别&#xff09;&#xff1a;https://mp.weixin.qq.com/s/BvotXrFXwYvGWpqHKoj3uQHTTP/2 指纹识别和Tls指纹类似也是一种 Web 服务器可以依赖指纹来识…

中兴智能视觉大数据:人脸识别技术目前处于“用的不够,用的不好”

中兴智能视觉大数据报道&#xff1a;在2018年5月30日举行的“人脸识别等AI技术在校园周边安全中的应用”研讨会上&#xff0c;中国人民大学危机管理研究中心主任唐钧指出&#xff0c;人脸识别等AI技术具有“精细识别”、“提前干预”、“及时处置”等优势&#xff0c;有利于促进…

C#反射,性能优化,不止于优化

“ 架构师的价值&#xff0c;在于独立且理性的思考”想要写出灵活而且具有更好适应性的代码&#xff0c;反射是首选方案。反射赋予程序在运行时动态创建实例的能力&#xff0c;可以在程序运行时&#xff08;而非编译时&#xff09;获取实例类型&#xff0c;获取元数据信息&…

设计模式C++实现--Observer模式

2019独角兽企业重金招聘Python工程师标准>>> 观察者模式 当对象间存在一对多关系时&#xff0c;则使用观察者模式&#xff08;Observer Pattern&#xff09;。比如&#xff0c;当一个对象被修改时&#xff0c;则会自动通知它的依赖对象。观察者模式属于行为型模式。…

Liunx 安装mysql 5.6.16

2019独角兽企业重金招聘Python工程师标准>>> 1.卸载原有的mysql 1)先查看原有的mysql rpm -qa|grep -i mysql 2)删除 mysql rpm -e --nodeps 包名 3)删除老版本 mysql的开发头文件和库 rm -fr /usr/lib/mysql rm -fr /usr/include/mysql 注意&#xff1a;卸载后/va…

数据挖掘 pandas基础入门之操作

为什么80%的码农都做不了架构师&#xff1f;>>> 统计 import pandas import numpy# 通过传递一个 numpyarray&#xff0c;时间索引以及列标签来创建一个DataFrame&#xff1a; dates pandas.date_range("20180509", periods6) df pandas.DataFrame(num…