连接rabbit
需要使用到RabbitMQ.Client.dll
下载地址:https://www.rabbitmq.com/devtools.html
命名空间 RabbitMQ.Client
用到的几个类或接口
IConneciton : 链接类,用来链接Rabbit 服务器
IModel: 信道,使用此来与Rabbit 进行收发消息,由IConnection 生成
ConnectionFactory: 链接工厂,用来建立链接
链接示例:
private IOnnection conn;
private IModel channel;
private readonly ConnecitonFactory factory = new ConnectionFactory();
public void Connection(){
try{
factory.UserName = "用户名";
factory.Password = "密码";
factory.VirtualHost = "虚拟主机";
factory.HostName = "服务器ip地址";
factory.Port = "服务器端口";
//连接断开是否自动恢复
factory.AutomaticRecoveryEnable = true;
conn = factory.CreateConnection();
channel = conn.CreateModul();
}catch(Exception e){
//链接失败
}
}
声明交换机/删除交换机
channel.ExchangeDeclare(exchangename,type,isDurable,autodelete,arguments);
exchangename:交换机名称,
type:交换机的类型 direct 直连 fanout 扇形 topic 主题 header 头部
isDurable: 持久化 持久化保存的是交换机的名称、类型、以及属性
未选择持久化的路由,rabbit 宕机 路由将会被删除
autodelete:与队列绑定的所有交换机或者队列 取消绑定后将会自动删除交换机
arguments:拓展参数
alternate-exchange:当消息无法路由时,投递到的备用交换机
注: 声明交换机是幂等的,但是前提是两次声明的参数是一致的,如果参数不一致第二次声明将会导致异常,并且异常产生后,信道将会断开(触发ModelShutdown事件),需要重新创建信道。
交换机类型
direct : 投递消息时路由键完全匹配才能正常投递消息
fanout : 忽略路由键,发送给所有与之绑定的队列或交换机
topic: 绑定的路由键可以使用统配符, 规则: 必须由(.)分割单词列表。
* 表示匹配一个单词
# 表示匹配 0个或多个单词
ExchangeDeclareNoWait: 异步声明交换机,无需等待
ExchangeDeclarePassive : 用来检查交换机是否存在,不存在引发异常,信道将会被关闭!
删除交换机
ExchangeDelete(exchange); 删除交换机
ExchangeDelete(exchange,ifUnused) ifUnused true 表示未被使用的情况下才被删除,false 表示直接删除
如果删除失败引发异常,信道断开
声明消息队列/删除消息队列
channel.QueueDeclare(queuename,durable,exclusive,autodelete,arguments);
queuename:队列名称
durable:持久化 持久化保存队列的名称,属性,以及消息队列中的消息 显然,这将影响性能,不持久化这些将会保存在内存中
exclusive:独占(排它),表示只有声明该队列的链接可见,只有声明它的链接才能使用该队列。当链接断开时,队列将会被自动删除 独占队列只能由一个连接声明,一旦有一个连接声明后,其他连接声明将会引发错误。
autodelete:自动删除,当与队列绑定的所有交换机解除绑定后队列将会自动删除
arguments:拓展参数
x-message-ttl : 6000 设置队列中的消息6000毫秒过期
x-expires : 设置当前的queue在指定的时间内,没有消费者来获取消息将会删除队列
x-max-length: 队列最大就绪的消息条目数量
x-max-length-bytes: 队列最大的就绪消息内容大小
x-overflow: drop-head/reject-publish 当消息溢出时 删除头部消息/拒绝消息
x-dead-letter-exchange: 当消息被丢弃(可能超时删除,也能消息被拒绝消费者拒绝,也可能其他原因)时将消息投递到哪个交换机,与x-dead-routing-key 同时使用
x-dead-routing-key:当消息被丢弃时,消息投递用的路由键
x-max-priority : 设置队列的优先级,优先级高的会优先发送给消费者
x-queue-mode: default / lazy. 设置为lazy 表示消息都存储在磁盘中,当消费者需要的时候才加载到内存中。
当消息大量积累的情况应该启用。
x-queue-master-locator: 集群使用,与镜像队列相关。
不带参数声明队列将得到一个 独占的自动删除的名字随机的队列
使用QueueDeclareNowait 异步创建,能快速返回但是没有返回值
QueueDeclarePassive: 获取队列的信息,如果队列不存在则引发异常
删除队列
QueueDelete(queue): 删除消息队列
QueueDelete(queue,ifUnused,ifEmpty)
ifUnused true 表示未使用才可被删除
isEmpty true 表示是空队列才可被删除
删除队列返回值表示队列中的消息数量。
如果未能删除队列将引发异常,并且信道将断开
清空消息队列
queuePurge: 清空消息队列
返回值 消息的数量
绑定队列/交换机
//绑定队列
channel.QueueBind(queue,exchange,routingkey);
//绑定交换机
channel.ExchangeBind(destination,source,toutingkey);
//队列解除绑定
channel.QueueUnBind( queue,exchange,routingkey,arguments)
//交换机解除绑定
channel.ExchangeUnBind(destination,source,routingkey);
两者经过绑定建立类似消息通道,可以从source到destination进行消息传输。
注:两者之间可以建立多个绑定。
发送消息
channel.BasicPublish(exchange,routingkey,mandatory,immediate,null,Encoding.UTF8.GetBytes(msg));
exchange: 消息投递到哪个交换机, 消息只能投递到交换机,不能直接投递到队列
routingkey: 使用的路由键
mandatory:当为true 时,如果exchange根据自身类型 和消息routekey 路由到一个队列 那么会调用basic.return 方法将消息返回给生产者
immediate:当为true 时,消息路由到的所有队列没有消费者则将消息basic.return 返回给生产者
注意: rabbit 3.0 已经弃用 immediate ,设置为true 将会引发异常,并导致信道断开
argements:
body[]: 消息内容
路由键必须小于255个字节
接收消息
1.订阅模式:
继承 DefaultBasicConsumer 类
HandleBasicCancel(string consumertag)
HandleBasicConsumerOk(string consumertag)
HandleBasicCancelOk(string consumertag)
//接收到消息时触发
//consumertag: 消费者标记 当创建消费者时使用的参数
//deliverttag : 消息编号,从0开始递增
//redelivered:
//exchange: 从哪个路由器过来的
//routingkey: 路由键
//properties:
// body 消息内容
HandleBasicDeliver(string consumertag,ulong deliverytag,redelivered,exchange,routingkey,properties,byte[] body)
//当消费者信道断开时触发
model: 触发事件的信道
resason: 主机的一些信息,用来查看信道是什么原因断开的
HandleModelShutdown(IModel model,ShutdownEventArgs reason)
//绑定消费者
//queue: 订阅哪个消息队列中的消息
//noAck: true 表示消息不需要确认 false 表示消息需要确认
//consumertag: 消费者标记
//nolocal: true 查到别人给出的解释是 表示不接收相同链接过来的消息,但是我测试到这个参数没有任何作用,也许是我哪里理解错了
//exclusive: 独占 独占消费者将会排出其他消费者,使队里为其专用.
channel.BasicConsumer(queue,noAck,consumertag,nolocal,exclusive)
2.请求获取模式
BasicGet(queue,noAck) 返回值 BasicGetResult
queue: 队列名称
noAck : true 表示消息不需要确认 false 表示消息需要确认
如果queue 存在 没有消息则返回null
如果queue 不存在 则引发异常,信道关闭
BasicGetResult
exchange: 投递的交换机
routingkey : 投递的路由器
Redelivered : 是否是重新获取的(是不是被别人用过)
MessageCount : 取出消息后,队列中还有多少条消息
body: 消息的内容
BasicQos方法可设置一个信道最多有多少个未确认消息
事件
IModel 的事件
ModelShutDown 参数 IModel,ShutdownEvenArgs
信道关闭事件
犯过的错:
1.在事件中创建信道
2.在事件中调用Dispose() ; 将导致死循环。
BasicReturn IModel,BasicReturnEventArgs
当投递消息时使用mandatory 时,消息投递无法路由到队列时将会触发事件
BasicAcks : 使用 Confirm 确认模式发送成功的事件
BasicNacks : 使用Confirm 确认模式发送失败的事件