1、實現發送和接收,類RabbitMQServerT
注意:
鏈接隊列服務器時,參數必須和服務器配置一致
private string queue;//隊列名
private bool durable;//持久化
private bool exclusive;//獨佔
private bool autoDelete;//自動刪除
默認帳號guest不能遠程。
默認訪問隊列端口是5672,後臺網站端口默認是15672。
using System; using System.ServiceProcess; using MQServer.Log; using RabbitMQ.Client; using System.Text; using System.Configuration; using RabbitMQ.Client.Events; namespace MQServer { /// <summary> /// RabbitMQ消息隊列類 /// </summary> public class RabbitMQServerT { protected readonly Action<string, object> receive;//接收回調 private object penetrate;//接收回調透傳參數 private string queue;//隊列名 private bool durable;//持久化 private bool exclusive;//獨佔 private bool autoDelete;//自動刪除 private bool isBeginInvoke;//接收後業務是否異步,異步的話消息可能在確認前被其他線程讀走,造成重複讀。//不異步就阻塞。//異步請獨佔 //接收消息對象 private IConnection connection; private IModel channel; public bool IsReceive; private ConnectionFactory factory; private RabbitMQServerT() { } /// <summary> /// 使用默認配置參數 /// </summary> /// <param name="_receive">消費事件,空則不消費</param> /// <param name="_queue">消息路徑最後一層名字,可用於區分業務</param> /// <param name="_penetrate">接收回調透傳參數</param> public RabbitMQServerT(Action<string, object> _receive, string _queue = @"hello", object _penetrate = null) { queue = _queue; receive = _receive; penetrate = _penetrate; isBeginInvoke = false; durable = bool.Parse(ConfigurationManager.AppSettings["RabbitMQ_durable"].ToString());// exclusive = bool.Parse(ConfigurationManager.AppSettings["RabbitMQ_exclusive"].ToString());// autoDelete = bool.Parse(ConfigurationManager.AppSettings["RabbitMQ_autoDelete"].ToString());// factory = new ConnectionFactory(); factory.HostName = ConfigurationManager.AppSettings["RabbitMQHostName"];//RabbitMQ服務器 factory.UserName = ConfigurationManager.AppSettings["RabbitMQUserName"];//用戶名 factory.Password = ConfigurationManager.AppSettings["RabbitMQPassword"];//密碼 factory.Port = int.Parse(ConfigurationManager.AppSettings["RabbitMQPort"].ToString());// if (!string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings["RabbitMQVirtualHost"])) { factory.VirtualHost = ConfigurationManager.AppSettings["RabbitMQVirtualHost"];// } } /// <summary> /// 使用手動參數 /// </summary> /// <param name="_receive">消費事件,空則不消費</param> /// <param name="_queue">消息路徑最後一層名字,可用於區分業務</param> /// <param name="_penetrate">接收回調透傳參數</param> /// <param name="factory">連接隊列服務器</param> /// <param name="durable">持久化</param> /// <param name="exclusive">獨佔</param> /// <param name="autoDelete">自動刪除</param> /// <param name="isBeginInvoke">接收是否異步//異步請獨佔,否則異常</param> public RabbitMQServerT(Action<string, object> _receive, string _queue, object _penetrate, ConnectionFactory factory ,bool durable,bool exclusive, bool autoDelete,bool isBeginInvoke) { queue = _queue; receive = _receive; penetrate = _penetrate; this.factory = factory; this.durable = durable; this.exclusive = exclusive; this.autoDelete = autoDelete; this.isBeginInvoke = isBeginInvoke; //異步請獨佔,不然會重複讀 if (isBeginInvoke == true && exclusive == false) { throw new Exception("接收消息隊列對象RabbitMQServerT參數isBeginInvoke=true異步執行接收業務,如果要異步執行業務,請獨佔該消息exclusive=true,否則會被其他線程重複讀取。"); } } /// <summary> /// 發送消息 /// </summary> /// <param name="message"></param> public void Send(string message) { //發送消息隊列 try { using (var connection = factory.CreateConnection()) { using (var channel = connection.CreateModel()) { channel.QueueDeclare(queue, durable, exclusive, autoDelete, null);//創建一個消息隊列 var body = Encoding.UTF8.GetBytes(message); channel.BasicPublish("", queue, null, body); //開始傳遞 TLogHelper.Info(message, "RabbitMQServerTSend");//發送的內容寫進TXT } } } catch (Exception ex) { TLogHelper.Error(ex.Message, "發送消息隊列異常RabbitMQServerTSend:\n" + message); } } /// <summary> /// 進行接收消息隊列 /// </summary> public void Receive() { if (receive == null) { return; } IsReceive = true; try { connection = factory.CreateConnection(); channel = connection.CreateModel(); channel.QueueDeclare(queue, durable, exclusive, autoDelete, null); channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false); var consumer = new EventingBasicConsumer(channel); consumer.Received += (model, ea) => { try { var body = ea.Body.ToArray(); var message = Encoding.UTF8.GetString(body); //接收後業務 if (isBeginInvoke) { receive?.BeginInvoke(message, penetrate,(e)=>{ //確認消息 channel.BasicAck(ea.DeliveryTag, false); },null); } else { receive?.Invoke(message, penetrate); //確認消息 channel.BasicAck(ea.DeliveryTag, false); } } catch (Exception ex) { TLogHelper.Error(ex.Message, "接收消息隊列業務異常Received:"+queue); } finally { //再次生成接收 Receive(); } }; channel.BasicConsume(queue, true, consumer); } catch (Exception ex) { TLogHelper.Error(ex.Message, "接收消息隊列異常Receive"); } } /// <summary> /// 取消接收 /// </summary> public void EndReceive() { IsReceive=false; channel.Dispose(); connection.Dispose(); } } }
2、BLL實現消息業務
BaseMQBLL
using MQServer; using System; namespace BLL { /// <summary> /// 使用隊列業務基類 /// </summary> public abstract class BaseMQBLL { public readonly RabbitMQServerT MQ; private BaseMQBLL(){ } public BaseMQBLL(string queue,object _penetrate) { MQ = new MQServer.RabbitMQServerT((string source, object o) => { try { ReceiveBack(source, _penetrate); ////test //throw new Exception("測試消息異常"); } catch (Exception) { throw; } }, queue, _penetrate: null); } public abstract void ReceiveBack(string source, object receiveO); } }
TestHello : BaseMQBLL
using MQServer.Log; namespace BLL { public class TestHello : BaseMQBLL { public TestHello() :base("hello",null) { ////默認開啓接收 //MQ.Receive(); } public override void ReceiveBack(string source, object receiveO) { TLogHelper.Info(source, "讀取消息在rabbitmain"); } } }
3、記錄日誌
TLogHelper
using Newtonsoft.Json; using System; using System.IO; using System.Messaging; using System.Text; namespace MQServer.Log { public class TLogHelper { public static object _lock = new object(); public static void MQ(Message myMessage, string detail = "") { string msg = JsonConvert.SerializeObject(myMessage.Body); Write(msg, detail, "MessageQueue"); } public static void Info(string msg, string detail = "") { Write(msg, detail, "Info"); } public static void Info(object msg, string detail = "") { Write(JsonConvert.SerializeObject(msg), detail, "Info"); } public static void Error(string msg, string detail = "") { Write(msg, detail, "Error"); } private static void Write(string msg,string detail="", string title = "Info") { DateTime now = DateTime.Now; string logPath = System.Configuration.ConfigurationManager.AppSettings["MQServerTLogPath"]; if (!Directory.Exists(logPath)) { Directory.CreateDirectory(logPath); } logPath += now.ToString("yyyyMMdd") + ".txt"; lock (_lock) { FileStream fs = new FileStream(@logPath, FileMode.OpenOrCreate, FileAccess.Write); StreamWriter m_streamWriter = new StreamWriter(fs); m_streamWriter.BaseStream.Seek(0, SeekOrigin.End); m_streamWriter.WriteLine(); m_streamWriter.WriteLine(now.ToString("yyyyMMddHHmmssfff") + " " + title); if (!string.IsNullOrWhiteSpace(detail)) { m_streamWriter.WriteLine(detail); } m_streamWriter.WriteLine(msg); m_streamWriter.Flush(); m_streamWriter.Close(); fs.Close(); } } public static string Read() { string res = ""; string logPath = System.Configuration.ConfigurationManager.AppSettings["MQServerTLogPath"]; logPath += DateTime.Now.ToString("yyyyMMdd") + ".txt"; lock (_lock) { StreamReader fs = new StreamReader(@logPath, Encoding.UTF8); res = fs.ReadToEnd(); fs.Dispose(); } return res; } } }
4、Form窗體測試
RabbitMQForm : Form
using BLL; using System; using System.Windows.Forms; namespace WinFormActiveMQ { public partial class RabbitMQForm : Form { private Label la_main; private Timer tim; public RabbitMQForm() { InitializeComponent(); la_main = new Label(); la_main.Name = "la_main"; la_main.Width = 282; la_main.TabIndex = 0; Controls.Add(la_main); tim = new Timer(); tim.Interval = 1000; tim.Tick += CheckReceive; tim.Start(); } private void Form1_Load(object sender, EventArgs e) { la_main.Text = "RabbitMQ消息隊列,點擊開啓接收。"; } /// <summary> /// 檢測接收線程是否還在,不在了重新接收 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void CheckReceive(object sender, EventArgs e) { //測試Hello隊列 if (TestHello.Checked) { if (hello == null) { hello = new TestHello(); } if (!hello.MQ.IsReceive) { hello.MQ.Receive(); } } } //測試Hello隊列 static TestHello hello; private void TestHello_CheckedChanged(object sender, EventArgs e) { if (TestHello.Checked) { hello = new TestHello(); hello.MQ.Receive(); hello.MQ.Send("測試第一消息"); } else { hello.MQ.EndReceive(); hello = null; } } } }
RabbitMQForm
namespace WinFormActiveMQ { partial class RabbitMQForm { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.TestHello = new System.Windows.Forms.CheckBox(); this.SuspendLayout(); // // TestHello // this.TestHello.AutoSize = true; this.TestHello.Location = new System.Drawing.Point(13, 46); this.TestHello.Name = "TestHello"; this.TestHello.Size = new System.Drawing.Size(101, 19); this.TestHello.TabIndex = 0; this.TestHello.Text = "TestHello"; this.TestHello.UseVisualStyleBackColor = true; this.TestHello.CheckedChanged += new System.EventHandler(this.TestHello_CheckedChanged); // // RabbitMQForm // this.ClientSize = new System.Drawing.Size(282, 253); this.Controls.Add(this.TestHello); this.Name = "RabbitMQForm"; this.Text = "RabbitMQForm"; this.Load += new System.EventHandler(this.Form1_Load); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.CheckBox TestHello; } }
5、默認配置
<appSettings> <add key="MQServerTLogPath" value="d:/WinFormActiveMQLog/" /> <add key="RabbitMQHostName" value="192.168.0.233" /> <add key="RabbitMQUserName" value="admin" /> <add key="RabbitMQPassword" value="123456" /> <add key="RabbitMQPort" value="5672" /> <add key="RabbitMQVirtualHost" value="" /> <add key="RabbitMQ_durable" value="true" /> <add key="RabbitMQ_exclusive" value="false" /> <add key="RabbitMQ_autoDelete" value="false" /> </appSettings>