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就足够了 ,但是 分布式微服务 不可能是单机 ,将会有很多很多的工程 ,无法手动一个一个的发送刷新请求, 因此引入了消息中间件 ,常用的 消息中间件 是 ...
随机推荐
- zabbix4.0下zabbix-agentd安装
转:http://www.safecdn.cn/monitor/2018/12/zabbix4-0-zabbix-agentd-install/316.html 一 安装源和Zabbix的依赖包: 1 ...
- linux面试题-基础题1
第1章 基础题1 1.1 在装系统创建Linux分区时,一般至少需要创建两个分区( ) A.FAT.NTFS B. /usr.swap C. /boot.swap D.swap./ 1.2 ...
- 《面向对象程序设计(java)》第七周学习总结
1.实验目的与要求 (1)进一步理解4个成员访问权限修饰符的用途: (2)掌握Object类的常用API用法: (3)掌握ArrayList类用法与常用API: (4)掌握枚举类使用方法: (5)结合 ...
- leetcode2
/** * Definition for singly-linked list. * public class ListNode { * public int val; * public ListNo ...
- leetcode236
class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { ...
- This iPhone 6s is running iOS 11.3.1 (15E302), which may not be supported by this version of Xcode.
This iPhone 6s is running iOS 11.3.1 (15E302), which may not be supported by this version of Xcode.
- NetBeans 代码折叠
代码折叠 // <editor-fold> Your code goes here...// </editor-fold> 添加描述 // <editor-fold ...
- 深入理解Java虚拟机之Java内存区域随笔
1.java内存区域与内存溢出异常 Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域:1.程序计数器,2.栈(虚拟机栈和本地方法栈 ),3.堆,4.方法区(包含 ...
- jquery.validate和jquery.form配合实现验证表单后AJAX提交
基础代码其实很简单,之后一点一点扩充.最终代码写在最后. 表单: <form action="@Url.Action("AddColumns","Cont ...
- 特大数字之和,返回结果是字符串(考虑到数字特别大,如果相加会产生e)
自己做的,没有整理代码,还是做出来了: 做这个题时,最总要的一步思路就是,先让长度一致,然后从个位开始,每一个与每一个数字相加,如果大于10,则下一次另外两个数相加时加1 function add(a ...