1、RabbitMQListener,自定义消息监听器

using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using RabbitMQ.Client.Exceptions; namespace MQ_Receive
{
/// <summary>
/// RabbitMq消息监听器
/// </summary>
public class RabbitMqListener
{
private ConnectionFactory _factory;
private IConnection _con;
private IModel _channel;
private EventingBasicConsumer _consumer; private readonly string _rabbitMqUri;
private readonly string _exchangeType;
private readonly string _exchangeName;
private readonly string _queueName;
private readonly string _routeKey;
private Func<string, bool> _messageHandler; /// <summary>
/// RabbitMQ消息监听器,若指定的队列不存在,则自动创建队列。并在消息交换机上绑定指定的消息路由规则(路由key)
/// </summary>
/// <param name="rabbitMqUri">连接串,如 amqp://guest:guest@localhost:5672/</param>
/// <param name="exchangeName">消息交换机</param>
/// <param name="exchangeType">交换机类型,如 ExchangeType.Direct</param>
/// <param name="queueName">要监听的队列</param>
/// <param name="routeKey">消息路由key</param>
public RabbitMqListener(string rabbitMqUri, string exchangeName, string exchangeType, string queueName, string routeKey = "")
{
this._rabbitMqUri = rabbitMqUri;
this._exchangeName = exchangeName;
this._exchangeType = exchangeType;
this._queueName = queueName;
this._routeKey = routeKey;
} /// <summary>
/// 创建连接
/// </summary>
private void CreateConnection()
{
_factory = new ConnectionFactory
{
Uri = new Uri(_rabbitMqUri),
RequestedHeartbeat = ,
AutomaticRecoveryEnabled = true,
TopologyRecoveryEnabled = true,
NetworkRecoveryInterval = TimeSpan.FromSeconds()
}; _con = _factory.CreateConnection();
_con.ConnectionShutdown += (_sender, _e) => ReMessageListen();//掉线重新连接并监听队列消息
} /// <summary>
/// 创建信道
/// </summary>
private void CreateChannel()
{
_channel = _con.CreateModel();
_channel.ExchangeDeclare(_exchangeName, _exchangeType, true, false, null);
_channel.QueueDeclare(_queueName, true, false, false, null); //创建一个消息队列,用来存储消息
_channel.QueueBind(_queueName, _exchangeName, _routeKey, null);
_channel.BasicQos(, , true); //在非自动确认消息的前提下,如果一定数目的消息(通过基于consume或者channel设置Qos的值)未被确认前,不进行消费新的消息
} /// <summary>
/// 监听队列消息
/// </summary>
/// <param name="messageHandler">消息处理器,当监测到队列消息时回调该处理器</param>
/// <returns>监听状态</returns>
public bool MessageListen(Func<string, bool> messageHandler)
{
try
{
this.CreateConnection();
this.CreateChannel(); _consumer = new EventingBasicConsumer(_channel); //基于事件的消息推送方式
_consumer.Received += (_sender, _e) =>
{
string msg = Encoding.UTF8.GetString(_e.Body);
if (messageHandler != null)
{
this._messageHandler = messageHandler;
try
{
var isOk = this._messageHandler(msg);
if (isOk)
{
_channel.BasicAck(_e.DeliveryTag, false);
}
}
catch (Exception ex)
{
LoggerManager.ErrorLog.Error("消息处理器执行异常:" + ex.Message, ex);
}
}
}; _channel.BasicConsume(_queueName, false, _consumer); //手动确认
return true;
}
catch (Exception ex)
{
LoggerManager.ErrorLog.Error("尝试监听队列消息出现错误:" + ex.Message, ex);
}
return false;
} public void ReMessageListen()
{
try
{
//清除连接及频道
CleanupResource(); var mres = new ManualResetEventSlim(false); //初始化状态为false
while (!mres.Wait()) //每3秒监测一次状态,直到状态为true
{
if (MessageListen(_messageHandler))
{
mres.Set(); //设置状态为true并跳出循环
}
}
}
catch (Exception ex)
{
LoggerManager.ErrorLog.Error("尝试连接RabbitMQ服务器出现错误:" + ex.Message, ex);
}
} /// <summary>
/// 清理资源
/// </summary>
private void CleanupResource()
{
if (_channel != null && _channel.IsOpen)
{
try
{
_channel.Close();
}
catch (Exception ex)
{
LoggerManager.ErrorLog.Error("尝试关闭RabbitMQ信道遇到错误", ex);
}
_channel = null;
} if (_con != null && _con.IsOpen)
{
try
{
_con.Close();
}
catch (Exception ex)
{
LoggerManager.ErrorLog.Error("尝试关闭RabbitMQ连接遇到错误", ex);
}
_con = null;
}
}
}
}

2、调用代码

using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms; namespace MQ_Receive
{
public partial class Form1 : Form
{
private delegate void ChangeText(string text);
private readonly ChangeText _changeText; private static string rabbitHostUri = "amqp://guest:guest@localhost:5672/";
private static string exchangeName = "order-exchange";
private static string queueName = "order-message-test-queue";
private static string routeKey = "order-message-routeKey";
private static readonly object lockObj = new object(); private static RabbitMQListener _listener;
public static RabbitMQListener RabbitMQListener
{
get
{
if (_listener == null)
{
lock (lockObj)
{
if (_listener == null)
{
_listener = new RabbitMQListener(rabbitHostUri, exchangeName, ExchangeType.Direct, queueName, routeKey);
}
}
} return _listener;
}
}
private Func<string, bool> MessageHandler
{
get {
return (msg) =>
{
this.label1.Invoke(_changeText, new object[] { msg });
return true;
};
}
} public Form1()
{
InitializeComponent();
this.label1.Text = "";
this._changeText = SetText;
} private void Form1_Load(object sender, EventArgs e)
{
RabbitMQListener.MessageListen(MessageHandler);
} private void SetText(string text)
{
this.label1.Text += text + "\n";
}
}
}

RabbitMQ心跳检测与掉线重连的更多相关文章

  1. Netty — 心跳检测和断线重连

    一.前言 由于在通信层的网络连接的不可靠性,比如:网络闪断,网络抖动等,经常会出现连接断开.这样对于使用长连接的应用而言,当突然高流量冲击势必会造成进行网络连接,从而产生网络堵塞,应用响应速度下降,延 ...

  2. websocket-heartbeat-js心跳检测库正式发布

    前言: 两年前写了一篇websocket心跳的博客——初探和实现websocket心跳重连.  阅读量一直比较大,加上最近考虑写一个自己的npm包,因此就完成了一个websocket心跳的检测库.在这 ...

  3. 【Netty】利用Netty实现心跳检测和重连机制

    一.前言 心跳机制是定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性的机制.   我们用到的很多框架都用到了心跳检测,比如服务注册到 Eureka Server 之后会维 ...

  4. WebSocket心跳检测和重连机制

    1. 心跳重连原由 心跳和重连的目的用一句话概括就是客户端和服务端保证彼此还活着,避免丢包发生. websocket连接断开有以下两证情况: 前端断开 在使用websocket过程中,可能会出现网络断 ...

  5. Netty学习篇④-心跳机制及断线重连

    心跳检测 前言 客户端和服务端的连接属于socket连接,也属于长连接,往往会存在客户端在连接了服务端之后就没有任何操作了,但还是占用了一个连接:当越来越多类似的客户端出现就会浪费很多连接,netty ...

  6. ws & websocket & 掉线重连

    ws & websocket & 掉线重连 reconnecting websocket https://github.com/joewalnes/reconnecting-webso ...

  7. rabbitmq心跳机制与配置

    最近,我们有些在阿里云上的应用总是有客户端出现异常和信息推送不及时的情况,检查mq日志,发现高峰期不停的有心跳超时,如下: =ERROR REPORT==== 21-Dec-2016::12:38:0 ...

  8. javascript websocket 心跳检测机制介绍

    ====测试代码: ==index.html <!DOCTYPE html> <html lang="en"> <head> <meta ...

  9. socket心跳检测

    一.什么是心跳检测 判断对方(设备,进程或其它网元)是否正常动行,一般采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经当掉.用于检测TCP的异常断开. 基本原因是服务器端不能 ...

随机推荐

  1. Winform的控件以及DataGridView的一般使用

    先上学习测试的一些截图 1:获取多个控件上面的值(checkbox,combobox,textbox,radiobutton) 2:获取到选择行的主键ID的value,方便我们进一步CURD 3:获取 ...

  2. Java自学-集合框架 遍历

    遍历ArrayList的三种方法 步骤 1 : 用for循环遍历 通过前面的学习,知道了可以用size()和get()分别得到大小,和获取指定位置的元素,结合for循环就可以遍历出ArrayList的 ...

  3. git did not exit cleanly (exit code 1) 的解决办法

    问题描述: 关于Git的使用,在通常情况下,习惯于先在本地创建一个本地仓库,然后将项目提交到本地master,再将本地master中的项目Push 到远程仓库中,这样问题就来了. 具体错误信息如下: ...

  4. GSOAP服务卡住?

    很久以前参考了https://www.genivia.com/doc/soapdoc2.html 中的一段: How to Create a Multi-Threaded Stand-Alone Se ...

  5. Python从零开始——集合Set

    一:Python集合知识概览 二:Python的特性.格式.以及各序列结构对比 三:Python集合set的创建 四:集合常用操作之——添加元素 五:集合常见操作之——删除元素 六:集合常见操作之—— ...

  6. Win7共享只看到部分文件

    把192.168.70.88这台机器的Android目录做为共享文件夹. 共享端:windows server 用户端:其它pc机安装windows7 或windows 10 在用户端只能看到部分文件 ...

  7. conan使用(四)--打包二进制库

    前面总结过如何打包一个存头文件库,那种情况下非常简单,因为只需要将源文件拷贝就行了.现在来研究下如何打包一个正常情况下会生成动态库或静态库的包.参考文档:https://docs.conan.io/e ...

  8. Java并发--Java中的CAS操作和实现原理

    版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/CringKong/article/deta ...

  9. 吴丽丽-201871010123《面向对象程序设计(Java)》第七周学习总结

    吴丽丽-201871010123<面向对象程序设计(Java)>第七周学习总结 项目 内容 这个作业属于哪个课程 http://www.cnblogs.com/nwnu-daizh/ 这个 ...

  10. 201871010106-丁宣元 《面向对象程序设计(java)》第四周学习总结

    201871010106-丁宣元 <面向对象程序设计(java)>第四周学习总结 正文开头 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-da ...