RabbitMQ心跳检测与掉线重连
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心跳检测与掉线重连的更多相关文章
- Netty — 心跳检测和断线重连
一.前言 由于在通信层的网络连接的不可靠性,比如:网络闪断,网络抖动等,经常会出现连接断开.这样对于使用长连接的应用而言,当突然高流量冲击势必会造成进行网络连接,从而产生网络堵塞,应用响应速度下降,延 ...
- websocket-heartbeat-js心跳检测库正式发布
前言: 两年前写了一篇websocket心跳的博客——初探和实现websocket心跳重连. 阅读量一直比较大,加上最近考虑写一个自己的npm包,因此就完成了一个websocket心跳的检测库.在这 ...
- 【Netty】利用Netty实现心跳检测和重连机制
一.前言 心跳机制是定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性的机制. 我们用到的很多框架都用到了心跳检测,比如服务注册到 Eureka Server 之后会维 ...
- WebSocket心跳检测和重连机制
1. 心跳重连原由 心跳和重连的目的用一句话概括就是客户端和服务端保证彼此还活着,避免丢包发生. websocket连接断开有以下两证情况: 前端断开 在使用websocket过程中,可能会出现网络断 ...
- Netty学习篇④-心跳机制及断线重连
心跳检测 前言 客户端和服务端的连接属于socket连接,也属于长连接,往往会存在客户端在连接了服务端之后就没有任何操作了,但还是占用了一个连接:当越来越多类似的客户端出现就会浪费很多连接,netty ...
- ws & websocket & 掉线重连
ws & websocket & 掉线重连 reconnecting websocket https://github.com/joewalnes/reconnecting-webso ...
- rabbitmq心跳机制与配置
最近,我们有些在阿里云上的应用总是有客户端出现异常和信息推送不及时的情况,检查mq日志,发现高峰期不停的有心跳超时,如下: =ERROR REPORT==== 21-Dec-2016::12:38:0 ...
- javascript websocket 心跳检测机制介绍
====测试代码: ==index.html <!DOCTYPE html> <html lang="en"> <head> <meta ...
- socket心跳检测
一.什么是心跳检测 判断对方(设备,进程或其它网元)是否正常动行,一般采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经当掉.用于检测TCP的异常断开. 基本原因是服务器端不能 ...
随机推荐
- RocketMQ多master多salve集群搭建
一.RocketMQ集群模式简介 单Master方式 风险比较大, 一旦Broker重启或者宕机, 将导致整个环境不可用, 不建议线上使用. 多Master模式 一个集群中没有slave, 全是mas ...
- 高性能TcpServer(C#) - 1.网络通信协议
高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...
- 读《TCP/IP详解》:TCP
TCP(Transmission Control Protocol,传输控制协议),位于传输层,提供一种面向连接.可靠的字节流服务. 字节流服务(Byte Stream Service)是指,为了方便 ...
- 苹果审核之遇到IPV6问题被拒的解决方法
情景: 等待苹果审核上线时,发现因为IPV6被拒了.这是悲剧,以下是苹果审核给我的理由: We discovered one or more bugs on Wi-Fi connected to an ...
- 个人项目:WC
一.GitHub项目地址:https://github.com/lseap/myWC 二.PSP表格: PSP2.1 Personal Software Process Stages 预估耗时(分钟) ...
- K-means 和 EM 比较
回顾 前几篇对 k-means 有过理解和写了一版伪代码, 因为思想比较非常朴素, 就是初始化几个中心点, 然后通过计算距离的方式, "物以类聚", 不断迭代中心点, 最后收敛, ...
- flask那些事(一)
flask配置文件 flask路由系统 @app.route() 装饰器中的参数 如果不明白装饰器 点击这里 methods : 当前 url 地址,允许访问的请求方式 @app.route(&quo ...
- ezdml设计数据库
数据结构和设计的介绍 ezdml软件:https://www.lanzous.com/i6ew2pe 1 用ezdml设计数据表然后导出到mysql数据库中 点击生成模型 2 选择库 3 点击开始生成
- Linux Workqueue【转】
转自:http://kernel.meizu.com/linux-workqueue.html 21 August 2016 Workqueue 是内核里面很重要的一个机制,特别是内核驱动,一般的 ...
- 5.1 RDD编程
一.RDD编程基础 1.创建 spark采用textFile()方法来从文件系统中加载数据创建RDD,该方法把文件的URL作为参数,这个URL可以是: 本地文件系统的地址 分布式文件系统HDFS的地址 ...