RabbitMQ与消息总线
Windows环境安装RabbitMQ,https://www.cnblogs.com/xibei666/p/5931267.html
1、消息发送流程
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using RabbitMQ;
using RabbitMQ.Client; namespace Practice_MQClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.label3.Text = "";
} private void button1_Click(object sender, EventArgs e)
{
var factory = new ConnectionFactory
{
HostName = "localhost",
VirtualHost = "/", //一个Host中可以设置多个虚拟主机
UserName = "guest",
Password = "guest",
}; //factory.Uri = new Uri("amqp://guest:guest@localhost:5672/"); //基于连接串的写法
var queueName = "order-message-queue";
var exchangeName = "order-exchange";
var routeKey = "order-message-routeKey";
var cn = factory.CreateConnection();
var channel = cn.CreateModel(); channel.ExchangeDeclare(exchangeName, ExchangeType.Direct, true, false, null); //创建消息交换机,用于分发消息到队列
channel.QueueDeclare(queueName, true, false, false, null); //创建一个消息队列,用来存储消息
channel.QueueBind(queueName, exchangeName, routeKey, null); //创建队列、消息交换机、路由Key三者的绑定关系 var msg = this.txtContent.Text;
var body = Encoding.UTF8.GetBytes(msg);
channel.BasicPublish(exchangeName, routeKey, null, body); //将消息发送给指定消息交换机,并设置使用的路由Key,后续的消息分发
//工作将由交换机根据路由Key匹配到指定的队列,并进行分发。 channel.Close();
cn.Close();
this.label3.ForeColor = Color.Chartreuse;
this.label3.Text = "发送成功";
}
}
}
2、消息消费过程
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using RabbitMQ.Client;
using RabbitMQ.Client.Events; namespace Practice.MQShow
{
//参考
//https://www.cnblogs.com/PatrickLiu/p/7193578.html
//https://www.cnblogs.com/leocook/p/mq_rabbitmq_4.html public partial class Form1 : Form
{
private delegate void ChangeText(string text);
private readonly ChangeText _changeText; public Form1()
{
InitializeComponent();
this.label1.Text = "";
this._changeText = SetText;
} private void Form1_Load(object sender, EventArgs e)
{
var factory = new ConnectionFactory
{
HostName = "localhost",
VirtualHost = "/",
UserName = "guest",
Password = "guest",
}; //var rs = channel.BasicGet(queueName, true); //消息获取方式一:主动拉取队列中的消息
//if (rs != null)
//{
// var body = rs.Body;
// Console.WriteLine(Encoding.UTF8.GetString(body));
//} var queueName = "order-message-queue"; //获取消息时只需要连上主机,通过队列名直接获取消息即可
var cn = factory.CreateConnection();
var channel = cn.CreateModel();
var consumer = new EventingBasicConsumer(channel); //消息获取方式二:基于推送的消息获取方式
consumer.Received += consumer_Received;
channel.BasicConsume(queueName, true, consumer);
} private void SetText(string text)
{
this.label1.Text += text + "\n";
} void consumer_Received(object sender, BasicDeliverEventArgs e)
{
this.label1.Invoke(_changeText, new object[] { Encoding.UTF8.GetString(e.Body) });
}
}
}
3、发送消息时消息确认
1、单个确认模式
// 开启发送方确认模式
channel.confirmSelect();
String message = String.format("时间 => %s", new Date().getTime());
channel.basicPublish("", config.QueueName, null, message.getBytes("UTF-8"));
if (channel.waitForConfirms()) {
System.out.println("消息发送成功" );
} 看代码可以知道,我们只需要在推送消息之前,channel.confirmSelect()声明开启发送方确认模式,再使用channel.waitForConfirms()等待消息被服务器确认即可。
2、批量确认模式 // 开启发送方确认模式
channel.confirmSelect();
for (int i = ; i < ; i++) {
String message = String.format("时间 => %s", new Date().getTime());
channel.basicPublish("", config.QueueName, null, message.getBytes("UTF-8"));
}
channel.waitForConfirmsOrDie(); //直到所有信息都发布,只要有一个未确认就会IOException
System.out.println("全部执行完成");
以上代码可以看出来channel.waitForConfirmsOrDie(),使用同步方式等所有的消息发送之后才会执行后面代码,只要有一个消息未被确认就会抛出IOException异常。
、异步确认模式 // 开启发送方确认模式
channel.confirmSelect();
for (int i = ; i < ; i++) {
String message = String.format("时间 => %s", new Date().getTime());
channel.basicPublish("", config.QueueName, null, message.getBytes("UTF-8"));
}
//异步监听确认和未确认的消息
channel.addConfirmListener(new ConfirmListener() {
@Override
public void handleNack(long deliveryTag, boolean multiple) throws IOException {
System.out.println("未确认消息,标识:" + deliveryTag);
}
@Override
public void handleAck(long deliveryTag, boolean multiple) throws IOException {
System.out.println(String.format("已确认消息,标识:%d,多个消息:%b", deliveryTag, multiple));
}
}); 异步模式的优点,就是执行效率高,不需要等待消息执行完,只需要监听消息即可。
4、消息消费时手动确认
private void Form1_Load(object sender, EventArgs e)
{
var factory = new ConnectionFactory
{
HostName = "localhost",
VirtualHost = "/",
UserName = "guest",
Password = "guest",
}; var queueName = "order-message-queue"; //获取消息时只需要连上主机,通过队列名直接获取消息即可
var cn = factory.CreateConnection();
var channel = cn.CreateModel();
var consumer = new EventingBasicConsumer(channel); //消息获取方式二:基于推送的消息获取方式
consumer.Received += (_sender, _e) =>
{
string msg = Encoding.UTF8.GetString(_e.Body);
this.label1.Invoke(_changeText, new object[] { msg });
if (msg != "")
{
channel.BasicAck(_e.DeliveryTag, false); //模拟消息消费手动确认,等于3的时候不确认消息
}
}; channel.BasicConsume(queueName, false, consumer); //设置消息确认方式为手动
}
5、死信队列使用
private void button4_Click(object sender, EventArgs e)
{
var factory = new ConnectionFactory();
factory.Uri = new Uri("amqp://guest:guest@localhost:5672/"); //基于连接串的写法
var exchangeName = "order-ttl-exchange";
var routeKey = "my-key"; var cn = factory.CreateConnection();
var channel = cn.CreateModel(); channel.ExchangeDeclare("dlx_exchange", ExchangeType.Direct, true, false, null);
channel.QueueDeclare("dlx_queue", true, false, false, null);
channel.QueueBind("dlx_queue", "dlx_exchange", routeKey, null); var args = new Dictionary<string, object>();
args.Add("x-message-ttl", );
args.Add("x-dead-letter-exchange", "dlx_exchange"); //设定死信队列所使用的exchange
args.Add("x-dead-letter-routing-key", routeKey); //设定死信队列所使用的routeKey channel.ExchangeDeclare(exchangeName, ExchangeType.Fanout, true, false, null);
channel.QueueDeclare("order-ttl-canceled", true, false, false, args);
channel.QueueBind("order-ttl-canceled", exchangeName, "", null); var msg = this.textBox1.Text;
var body = Encoding.UTF8.GetBytes(msg); channel.ConfirmSelect();//启用消息发送确认机制
channel.BasicPublish(exchangeName, "", null, body); var result = channel.WaitForConfirms();
if (result)
{
this.label1.ForeColor = Color.Chartreuse;
this.label1.Text = "发送成功";
}
else
{
this.label1.ForeColor = Color.Red;
this.label1.Text = "发送失败";
} channel.Close();
cn.Close();
}
5.1 断线重连 https://www.cnblogs.com/weschen/p/10847842.html
6、关于事务处理,参考 https://www.cnblogs.com/vipstone/p/9350075.html,https://www.jianshu.com/p/1ee6be549fda
7、 使用Masstransit开发基于消息传递的分布式应用
https://www.cnblogs.com/richieyang/p/5730785.html
https://www.cnblogs.com/richieyang/p/5492432.html
https://www.cnblogs.com/Andre/p/9579764.html
https://www.cnblogs.com/edisonchou/p/dnc_microservice_masstransit_foundation_part1.html
https://www.cnblogs.com/edisonchou/p/dnc_microservice_masstransit_foundation_part2.htmlhttps://www.cnblogs.com/qkbao/p/6952654.html
8、实际应用
https://www.cnblogs.com/itsoku123/p/10811003.html
https://www.cnblogs.com/itsoku123/p/10813423.html
9、其他
https://github.com/sheng-jie/RabbitMQ
https://www.sojson.com/blog/48.html
https://www.cnblogs.com/wangiqngpei557/p/6158094.html
RabbitMQ与消息总线的更多相关文章
- 微服务实战(三):落地微服务架构到直销系统(构建基于RabbitMq的消息总线)
从前面文章可以看出,消息总线是EDA(事件驱动架构)与微服务架构的核心部件,没有消息总线,就无法很好的实现微服务之间的解耦与通讯.通常我们可以利用现有成熟的消息代理产品或云平台提供的消息服务来构建自己 ...
- Spring Cloud构建微服务架构(七)消息总线
先回顾一下,在之前的Spring Cloud Config的介绍中,我们还留了一个悬念:如何实现对配置信息的实时更新.虽然,我们已经能够通过/refresh接口和Git仓库的Web Hook来实现Gi ...
- 消息总线VS消息队列
前段时间实现了一个基于RabbitMQ的消息总线,实现的过程中自己也在不断得思考.总结以及修正.需要考虑各个维度:效率.性能.网络.吞吐量.甚至需要自己去设想API可能的使用场景.模式.不过能有一件事 ...
- 通过消息总线Spring Cloud Bus实现配置文件刷新(使用Kafka或RocketMQ)
如果需要客户端获取到最新的配置信息需要执行refresh,我们可以利用webhook的机制每次提交代码发送请求来刷新客户端,当客户端越来越多的时候,需要每个客户端都执行一遍,这种方案就不太适合了.使用 ...
- 八. SpringCloud消息总线
1. 消息总线概述 1.1 分布式配置的动态刷新问题 Linux运维修改Github上的配置文件内容做调整 刷新3344,发现ConfigServer配置中心立刻响应 刷新3355,发现ConfigC ...
- Spring Cloud Bus 消息总线 RabbitMQ
Spring Cloud Bus将分布式系统中各节点通过轻量级消息代理连接起来. 从而实现例如广播状态改变(例如配置改变)或其他的管理指令. 目前唯一的实现是使用AMQP代理作为传输对象. Sprin ...
- eShopOnContainers学习系列(三):RabbitMQ消息总线实践
今天研究了下eShopOnContainers里的RabbitMQ的使用,在项目里是以封装成消息总线的方式使用的,但是仍然是以其发布.订阅两个方法作为基础封装的,我们今天就来实际使用一下. 为了简单起 ...
- Spring Cloud(十一)高可用的分布式配置中心 Spring Cloud Bus 消息总线集成(RabbitMQ)
详见:https://www.w3cschool.cn/spring_cloud/spring_cloud-jl8a2ixp.html 上一篇文章,留了一个悬念,Config Client 实现配置的 ...
- spring cloud bus 消息总线 动态刷新配置文件 【actuator 与 RabbitMQ配合完成】
1.前言 单机刷新配置文件,使用actuator就足够了 ,但是 分布式微服务 不可能是单机 ,将会有很多很多的工程 ,无法手动一个一个的发送刷新请求, 因此引入了消息中间件 ,常用的 消息中间件 是 ...
随机推荐
- JavaScript 下拉框 左边添加至右边
关于如何实现右边下拉框中选项的排序一时没有好的解决方法,等想到了回来补充 <!DOCTYPE html> <html> <head> <meta charse ...
- grep -A -B -C 显示抓取的前后几行参数
我经常用grep找东西,比如用户名和密码.大部分站点和用户名和密码都是在一样的,方便grep查找.有时,为了文本好看,我会放在多行.比如 wikipedia多个语言版本上有多个账号,就放在wikipe ...
- python学习Day4 流程控制(if分支,while循环,for循环)
复习 1.变量名命名规范 -- 1.只能由数字.字母 及 _ 组成 -- 2.不能以数字开头 -- 3.不能与系统关键字重名 -- 4._开头有特殊含义 -- 5.__开头__结尾的变量,魔法变量 - ...
- [Ting's笔记Day8]活用套件carrierwave gem:(3)Deploy图片上传功能到Heroku网站
前情提要: 身为Ruby新手村民,创造稳定且持续的学习步调很重要,我用的方法就是一周在IT邦写三篇笔记,希望藉由把笔记和遇到的bug记录下来的过程,能帮助到未来想用Ruby on Rails架站的新手 ...
- pycharm 下使用tensorflow 之环境配置
我们常常看代码使用ide里面看,而且还可以看到调试信息(虽然tensorflow有专门的调试介绍哈) 但是,常常代码在终端里面执行可以直接执行,但是到pycharm里面就会出现各种问题,常见的就是找不 ...
- 加入 Jungle Testnet
[加入 Jungle Testnet] 主网测试需要消耗大量 EOS,JungleTestnet为我们提供了一个测试用的EOS主链,上面的EOS可以通过申请获得.每6小时可以申请100EOS. [创建 ...
- Unity之AssetBundle打包
AssetBundle Resources:表示U3D自动将资源打成一个AssetBundle包,所有放在Resources下的文件夹都会打成一个AssetBundle包,资源非常大,Resource ...
- 转:JMeter监控内存及CPU ——plugin插件监控被测系统资源方法
JMeter监控内存及CPU ——plugin插件监控被测系统资源方法 jmeter中也可以监控服务器的CPU和内存使用情况,但是需要安装一些插件还需要在被监测服务器上开启服务. 1.需要的插件准备 ...
- Laravel5 (cli)命令行执行脚本及定时任务
Artisan是Laravel自带的命令行接口名称,它提供了很多有用的命令想要查看所有可用的Artisan命令,可使用list命令查看: 1 php artisan list 每个命令都可以用help ...
- [leetcode]243. Shortest Word Distance最短单词距离
Given a list of words and two words word1 and word2, return the shortest distance between these two ...