netcore之RabbitMQ入门
简介
RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息中间件,基于Erlang语言编写。
AMQP是什么
AMQP 0-9-1(高级消息队列协议)是一种消息传递协议,它允许一致的客户端应用程序与一致的消息传递中间件代理进行通信。
消息传递代理接收来自发布者(发布它们的应用程序,也称为生产者)的消息,并将它们路由到消费者(处理它们的应用程序)。
由于它是一个网络协议,发布者、消费者和代理都可以驻留在不同的机器上。
AMQP 0-9-1模型简介
AMQP 0-9-1模型具有以下世界视图:消息发布到交换,这通常与邮局或邮箱进行比较。交换然后使用名为绑定的规则将消息副本分发到队列。然后,代理将消息传递给订阅队列的消费者,或者消费者根据需要从队列获取/拉取消息。
发布消息时,发布者可以指定各种消息属性(消息元数据)。有些元数据可以由代理使用,但是,其余的元数据对代理是完全不透明的,只能由接收消息的应用程序使用。
网络不可靠,应用程序可能无法处理消息,因此AMQP 0-9-1模型具有消息确认的概念:当消息传递给消费者时,消费者会自动或在应用程序开发人员选择时立即通知代理。当消息确认正在使用时,代理将仅在收到消息(或消息组)通知时从队列中完全删除消息。
例如,在某些情况下,当消息无法路由时,消息可能会返回给发布者、丢弃,或者,如果代理实现扩展,则将消息放入所谓的“死信队列”。发布者通过使用某些参数发布消息来选择如何处理这种情况。
队列、交换和绑定统称为AMQP实体。
交换和交换类型
Rabbitmq中的核心思想,生产者不会把消息直接发送到队列当中,一般生产者是向交换机发送消息,交换机把消息推送到队列当中。
交换机是发送消息的实体,交换机接收消息并将消息路由到零个或者多个队列当中,使用的路由算法取决于绑定的交换类型和规则,因此AMQP 0-9-1提供了以下四种交换类型:
- Direct exchange 直接交换
- Fanout exchange 主题交换
- Topic exchange 头交换
- Headers exchang 扇形交换
除了交换类型之外,还使用许多属性声明交换其中最重要的是:
- 耐久性(Durability) :交易所在经纪人重启后仍能存活
- 自动删除(Auto-delete):当最后一个队列与其解除绑定时,将删除Exchange
- 参数(arguments) :可选,由插件和特定于代理的功能使用
交换可以是持久的,也可以是暂时的。持久性交易所能在经纪重启后存活下来,而短暂性交易所则不能(当经纪重新上线时,必须重新申报)。并非所有的场景和用例都需要持久的交换。
本文主要记录了学习RabbitMQ
开发准备
- RabbitMQHelper :该工程主要封装了RabbitMQ的公用方法
- RabbitMQClient :该工程为生产者
- RabbitMQServer :该工程为消费者
- 环境准备 :RabbitMQ 安装还请自行百度
1.创建RabbitMQHelper工程文件
2.安装依赖
通过程序包管理器控制台或者nuget安装RabbitMQ.Client,默认项目选择RabbitMQHelper
install-pack RabbitMQ.client
2.1 添加帮助类所需实体
添加交换机实体
using System;
using System.Collections.Generic;
using System.Text; namespace RabbitMQHelper.Model
{
/// <summary>
/// 交换机实体
/// </summary>
public class ExchangeModel
{
/// <summary>
/// 交换机名称
/// </summary>
public string ExchangeName { get; set; }
/// <summary>
/// 交换机类型
/// </summary>
public string ExchangeType { get; set; }
/// <summary>
/// 路由key
/// </summary>
public string RouteKey { get; set; }
/// <summary>
/// 是否持久化
/// </summary>
public bool Durable { get; set; }
}
}
添加链接实体
using System;
using System.Collections.Generic;
using System.Text; namespace RabbitMQHelper.Model
{
/// <summary>
/// 连接实体
/// </summary>
public class HostModel
{
/// <summary>
/// 客户端账号
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 客户端密码
/// </summary>
public string PassWord { get; set; } /// <summary>
/// 连接地址
/// </summary>
public string Host { get; set; }
/// <summary>
/// 端口号
/// </summary> public int Port { get; set; }
public ExChangeModel ExChangeModel { get; set; }
/// <summary>
/// 虚拟路径
/// </summary>
public string VirtualHost { get; set; }
}
/// <summary>
/// RabbitMq实体
/// </summary>
public class ExChangeModel
{
/// <summary>
/// 队列名称
/// </summary>
public string QueueName { get; set; }
/// <summary>
/// 路由名称
/// </summary>
public string RouteKey { get; set; }
/// <summary>
/// 交换机名称
/// </summary> public string ExChangeName { get; set; }
}
}
2.3 添加持久化链接单例
此处主要是考虑到如果每一次请求都去创建一个连接的话,比较耗时,而且rabbitMQ官方也建议使用长连接的方式进行通信,所以此处用一个单例进行存储连接信息
using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Text; namespace RabbitMQHelper.core
{
public class RabbitMQSingleton
{
private static RabbitMQSingleton rabbitServicesSingleton;
static RabbitMQSingleton()
{
rabbitServicesSingleton = new RabbitMQSingleton();
}
private Dictionary<string, IConnection> RabbitMQconn = new Dictionary<string, IConnection>();
public static RabbitMQSingleton GetInstance()
{
return rabbitServicesSingleton;
}
/// <summary>
/// 添加MQ连接
/// </summary>
/// <param name="key">连接名</param>
/// <param name="value">内容</param>
public void SetRabbitMqConn(string key, IConnection value)
{
if (!RabbitMQconn.ContainsKey(key))
{
RabbitMQconn.Add(key, value);
}
}
/// <summary>
/// 获取rabbitmq所有连接信息
/// </summary>
/// <returns></returns>
public Dictionary<string, IConnection> GetRabbitMQconn()
{
return RabbitMQconn;
}
/// <summary>
/// 移除连接
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool RemoveMQconn(string key)
{
bool sflag = true;
try
{
if (RabbitMQconn.ContainsKey(key))
{
RabbitMQconn.Remove(key);
}
}
catch (Exception)
{
sflag = false;
throw;
}
return sflag;
}
}
}
2.4.添加辅助类
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using RabbitMQHelper.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text; namespace RabbitMQHelper
{
public class RabbitHelper
{
private readonly ConnectionFactory factory = null;
public RabbitHelper(HostModel hostModel)
{
// 创建连接工厂
factory = new ConnectionFactory
{
UserName = hostModel.UserName,//连接用户名
Password = hostModel.PassWord,//连接密码
HostName = "localhost",//连接地址
Port = hostModel.Port,//端口号
//VirtualHost = hostModel.VirtualHost
};
}
/// <summary>
/// 创建连接
/// </summary>
/// <returns></returns>
public IConnection Connection()
{ IConnection connection = null;
try
{
factory.AutomaticRecoveryEnabled = true;//自动重连
connection = factory.CreateConnection();
}
catch (Exception)
{
throw new Exception("连接失败!~~~~~");
}
return connection;
}
/// <summary>
///
/// </summary>
/// <param name="conn"></param>
/// <param name="queueName"></param>
/// <param name="msg"></param>
/// <param name="exchangeModel"></param>
/// <returns></returns>
public bool sendMsg(IConnection conn, string queueName, string msg, ExchangeModel exchangeModel)
{
bool sflag = true;
try
{
//var channel = conn.CreateModel();
using (var channel = conn.CreateModel())
{ //1交换机,交换机类型
channel.ExchangeDeclare(exchangeModel.ExchangeName, exchangeModel.ExchangeType);
//队列名称,是否持久化,独占的队列,不使用时是否自动删除,
channel.QueueDeclare(queueName, exchangeModel.Durable,false,false,null);
//转换成byte数组
var sendBytes = Encoding.UTF8.GetBytes(msg);
//设置持久化参数
var properties = channel.CreateBasicProperties();
properties.DeliveryMode = ;//1表示不持久,2表示持久化
if (!exchangeModel.Durable)
{
properties = null;
}
//发送消息:交换机名称,路由,持久化参数,消息内容
channel.BasicPublish(exchangeModel.ExchangeName, exchangeModel.RouteKey, properties, sendBytes);
}
}
catch (Exception)
{ sflag = true;
throw;
}
return sflag;
}
/// <summary>
/// 接收消息
/// </summary>
/// <param name="connection"></param>
/// <param name="queueName"></param>
/// <param name="durable"></param>
/// <returns></returns>
public string ConsumMsg(IConnection connection,string queueName, ExchangeModel exchangeModel)
{
string msg = string.Empty;
var channel = connection.CreateModel(); //队列绑定:队列名称,交换机名称,路由
channel.QueueBind(queueName, exchangeModel.ExchangeName, exchangeModel.RouteKey, null);
var consumer = new EventingBasicConsumer(channel);
//接收到消息事件
consumer.Received += (ch, ea) =>
{
var message = Encoding.UTF8.GetString(ea.Body);
msg = message;
Console.WriteLine($"收到消息: {message}");
//确认该消息已被消费
channel.BasicAck(ea.DeliveryTag, false);
};
//启动消费者 设置为手动应答消息
channel.BasicConsume(queueName, false, consumer);
return msg; } }
}
2.5添加生产者类
using RabbitMQ.Client;
using RabbitMQHelper.core;
using RabbitMQHelper.IServer;
using RabbitMQHelper.Model;
using System;
using System.Collections.Generic;
using System.Text; namespace RabbitMQHelper.Server
{
public class SendService : ISendService
{
IConnection connection;//rabbitmq连接地址
private object obj=new object();//对象
RabbitHelper rabbitHelper;//rabbitHelper类 public SendService()
{
RabbitMQSingleton rabbitMQSingleton = RabbitMQSingleton.GetInstance();
Dictionary<string, IConnection> connDictionary = rabbitMQSingleton.GetRabbitMQconn();
if (connDictionary != null && connDictionary.Count > )
{
connection = connDictionary["test"];
}
else
{
HostModel hostModel = new HostModel();
hostModel.UserName = "admin";
hostModel.PassWord = "admin";
hostModel.Host = "127.0.0.1";
hostModel.Port = ;
//hostModel.VirtualHost = "/"; lock (obj)
{
rabbitHelper = new RabbitHelper(hostModel);
connection = rabbitHelper.Connection();
rabbitMQSingleton.SetRabbitMqConn("test", connection);
}
}
}
public bool CloseConnection()
{
throw new NotImplementedException();
}
public void SendMsg(string queueName, string msg)
{
ExchangeModel exchangeModel = new ExchangeModel();
exchangeModel.Durable = false;
exchangeModel.ExchangeName = "ClentName";
exchangeModel.ExchangeType = ExchangeType.Direct;
exchangeModel.RouteKey = "ClentRoute";
rabbitHelper.sendMsg(connection, queueName, msg, exchangeModel);
} //public void SendMsg(string msg)
//{ // throw new NotImplementedException();
//}
}
}
2.6添加消费者
using RabbitMQ.Client;
using RabbitMQHelper.core;
using RabbitMQHelper.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text; namespace RabbitMQHelper.Server
{
public class ConsumerServer
{
IConnection connection;//rabbitmq连接地址
private object obj = new object();//对象
RabbitHelper rabbitHelper;//rabbitHelper类 public ConsumerServer()
{
RabbitMQSingleton rabbitMQSingleton = RabbitMQSingleton.GetInstance();
Dictionary<string, IConnection> connDictionary = rabbitMQSingleton.GetRabbitMQconn();
if (connDictionary != null && connDictionary.Count > )
{
connection = connDictionary["test"];
}
else
{
HostModel hostModel = new HostModel();
hostModel.UserName = "admin";
hostModel.PassWord = "admin";
hostModel.Host = "127.0.0.1";
hostModel.Port = ;
//hostModel.VirtualHost = "/"; lock (obj)
{
rabbitHelper = new RabbitHelper(hostModel);
connection = rabbitHelper.Connection();
rabbitMQSingleton.SetRabbitMqConn("test", connection);
}
}
}
public string GetMsg(string queueName)
{
ExchangeModel exchangeModel = new ExchangeModel(); exchangeModel.ExchangeName = "ClentName";
exchangeModel.ExchangeType = ExchangeType.Direct;
exchangeModel.RouteKey = "ClentRoute";
return rabbitHelper.ConsumMsg(connection, queueName, exchangeModel);
}
}
}
3.添加RibbitMQClient项目(消息生产者)
创建控制台程序
using RabbitMQ.Client;
using RabbitMQHelper.IServer;
using RabbitMQHelper.Server;
using System; namespace RibbitMQClient
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("消息生产者开始生产数据!");
Console.WriteLine("输入exit退出!"); ISendService sendService = new SendService(); string input; do
{ input = Console.ReadLine(); sendService.SendMsg("Clent1", input);
} while (input.Trim().ToLower() != "exit"); }
}
}
4.创建RibbitMQServer 消费者模式
using RabbitMQHelper.Server;
using System;
using System.Text; namespace RibbitMQServer
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
ConsumerServer consumerServer = new ConsumerServer();
consumerServer.GetMsg("Clent1");
Console.WriteLine("消费者已启动");
Console.ReadKey(); }
}
}
5.运行程序
可正常接收数据
标注:如有理解不对的还请多指教,或者有好的实现方式也可一起讨论。
netcore之RabbitMQ入门的更多相关文章
- RabbitMQ入门学习系列(二),单生产者消费者
友情提示 我对我的文章负责,发现好多网上的文章 没有实践,都发出来的,让人走很多弯路,如果你在我的文章中遇到无法实现,或者无法走通的问题.可以直接在公众号<爱码农爱生活 >留言.必定会再次 ...
- 2.RABBITMQ 入门 - WINDOWS - 生产和消费消息 一个完整案例
关于安装和配置,见上一篇 1.RABBITMQ 入门 - WINDOWS - 获取,安装,配置 公司有需求,要求使用winform开发这个东西(消息中间件),另外还要求开发一个日志中间件,但是也是要求 ...
- RabbitMQ入门-从HelloWorld开始
从读者的反馈谈RabbitMQ 昨天发完<RabbitMQ入门-初识RabbitMQ>,我陆陆续续收到一些反馈.鉴于部分读者希望结合实例来讲 期待下篇详细,最好结合案例.谢谢! 哪都好,唯 ...
- RabbitMQ入门-高效的Work模式
扛不住的Hello World模式 上篇<RabbitMQ入门-从HelloWorld开始>介绍了RabbitMQ中最基本的Hello World模型.正如其名,Hello World模型 ...
- RabbitMQ入门-消息订阅模式
消息派发 上篇<RabbitMQ入门-消息派发那些事儿>发布之后,收了不少反馈,其中问的最多的还是有关消息确认以及超时等场景的处理. 楼主,有遇到消费者后台进程不在,但consumer连接 ...
- RabbitMQ入门-Topic模式
上篇<RabbitMQ入门-Routing直连模式>我们介绍了可以定向发送消息,并可以根据自定义规则派发消息.看起来,这个Routing模式已经算灵活的了,但是,这还不够,我们还有更加多样 ...
- RabbitMQ入门与使用篇
介绍 RabbitMQ是一个由erlang开发的基于AMQP(Advanced Message Queue)协议的开源实现.用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面都非常的优秀 ...
- [转]RabbitMQ入门教程(概念,应用场景,安装,使用)
原文地址:https://www.jianshu.com/p/dae5bbed39b1 RabbitMQ 简介 RabbitMQ是一个在AMQP(Advanced Message Queuing Pr ...
- RabbitMQ 入门指南——安装
RabbitMQ好文 Rabbitmq Java Client Api详解 tohxyblog-博客园-rabbitMQ教程系列 robertohuang-CSDN-rabbitMQ教程系列 Rabb ...
随机推荐
- 每秒100W请求,12306秒杀业务,架构如何优化?
如<同样是高并发,QQ/微博/12306的架构难度一样吗?>一文所述,同样是高并发场景,三类业务的架构挑战不一样: QQ类业务,用户主要读写自己的数据,访问基本带有uid属性,数据访问锁冲 ...
- JS MD5 返回二进制格式
今天靠大佬的帮助,成功的解决了一个弄了好久的问题.起因就是我们要对一个手机号进行加密. 加密方式是把一个字符串进行MD5加密之后,得到原始 16 字符二进制格式.然后把得到的这个字符作为AES的key ...
- ALV字段设置更改后,展示不同步的问题
案例: 一个需要用户交互的ALV,比如某字段设置为输入长度20,不区分大小写.用户要求输入长度改为50,且要求区分大小写. 处理方式: 如果本来ALV字段设置时,采用的是ref_table和ref_f ...
- iOS引导页(镂空效果)
推荐使用SDK:pod 'EAFeatureGuideView' 温馨提示:(引导的图片图标需要私人订制的可以用自己的,让UI提供) 参考链接:https://www.jianshu.com/p/c9 ...
- 个人项目开源之Django图书借阅系统源代码
Django写的模拟图书借阅系统源代码已开源到码云 源代码
- [转载] Java的四种引用关系
目录 1 强引用 (Final Reference) 2 软引用 (Soft Reference) 2.1 案例1: 软引用的垃圾回收 2.2 案例2: 软引用缓存的使用 2.3 软引用的应用场景 3 ...
- Mysql—数据恢复
根据.frm和.ibd文件恢复表结构和数据
- 【Https异常】This request has been blocked; the content must be served over HTTPS
一.问题出现场景 项目从http升级到https后,jsp页面存在发送http请求的情况下就会出现该异常.因为HTTPS 是 HTTP over Secure Socket Layer,以安全为目标的 ...
- Python-判断回文
# 回文单词是从左到右和从右到左读相同的单词. # 例如:"detartrated"和"evitative"是回文 str_in = input('Input: ...
- Linux下新增和使用系统调用
关键词:__SYSCALL().SYSCALL_DEFINEx().syscall()等等. 1. 为什么使用syscall 内核和用户空间数据交换有很多种方式:sysfs.proc.信号等等. 但是 ...