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的异常断开. 基本原因是服务器端不能 ...
随机推荐
- Java Scanner 类——获取用户的输入
创建Scanner对象语法 Scanner scan = new Scanner(System.in); 使用next()获取输入的字符串 import java.util.Scanner; publ ...
- 宣布Visual Studio Code Installer for Java
自从第一个Java语言服务器在微软苏黎世办公室的一个小型会议室的黑客马拉松中开发已经差不多3年了,该会议室的人员来自Red Hat,IBM,Codenvy和Microsoft,后来成为Visual S ...
- synchronized和volatile使用
synchronized和volatile volatile :保证内存可见性,但是不保证原子性: synchronized:同步锁,既能保证内存可见性,又能保证原子性: synchronized实现 ...
- linux应用管理
desktop文件的几个位置: /usr/share/applications ~/.local/share/applications /usr/local/share/applications li ...
- 设计模式之(十)装饰模式(DECORATOR)
在购买了一个房子后,如果是毛坯房,肯定不合适直接入住的.需要对它进行装修:地面找平贴地砖.批墙贴墙纸.吊顶装订以及买需要的家具,住进去以后也可能根据需要再添加或者去掉一些家具或者修改一些东西.所以的这 ...
- HttpHelper之我见
前几月一直用一个Http的访问类去调用WebApi,说句实话最开始没觉有什么,一是技术老,二是觉得比较简单,但是最近我一直关注云开发和AI这块儿微软技术,看到云平台调用API大多类似,所以回想这个早年 ...
- 010.[转] maven的三大生命周期
一.Maven的生命周期 Maven的生命周期就是对所有的构建过程进行抽象和统一.包含了项目的清理.初始化.编译.测试.打包.集成测试.验证.部署和站点生成等几乎所有的构建步骤. Maven的生命周期 ...
- 【IDE_IntelliJ IDEA】idea主题设置
参考博文: IDEA 炫酷的主题字体颜色设置 idea主题下载
- [TCP/IP]TCP服务端accept发生在三次握手的哪一个阶段
TCP服务端accept发生在三次握手之后 客户端socket()==>connect()==>write()==>read()服务端socket()==>bind()==&g ...
- ping脚本--无网不利
一.本文主要涉及的内容 二.预备知识 1.打印网络接口列表 2.提取IP地址的小套路 3.更改网卡的MAC地址 4.高速的ping工具:fping 三.套路连招 1.通过一个for循环和ping列出所 ...