关于RabbitMQ消息队列中广播消息监听服务的抽象类的定义,应该包含以下方法:
1.消息队列的名称
2.接收消息的数量
3.帮定的交换机(exchange)的名称
4.接收到消息后的自定义处理方法
5.消息过滤方法
实现代码如下,基于Net5实现:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using JuCheap.Core.MQ;
using JuCheap.Models.Enum;
using JuCheap.Models.MQMessage;
using Newtonsoft.Json;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace JuCheap.Core
{
/// <summary>
/// 广播消息队列监听抽象类
/// </summary>
public abstract class JuCheapMQBaseListner
{
private ManualResetEvent _manualResetEvent = new(false);
private readonly ILogger<MTalkMQBaseListner> _logger;
private readonly IConfiguration _config;
public JuCheapMQBaseListner(ILoggerFactory loggerFactory, IConfiguration config)
{
_logger = loggerFactory.CreateLogger<MTalkMQBaseListner>();
_config = config;
}
/// <summary>
/// 获取RabbitMQ队列名称
/// </summary>
/// <returns></returns>
public abstract string GetQueueName();
/// <summary>
/// 获取交换机名称
/// </summary>
/// <returns></returns>
public abstract string GetExchangeName();
/// <summary>
/// 获取接收消息的条数(小于等于0为不限制)
/// </summary>
/// <returns></returns>
public abstract ushort GetReceiveMessageNumber();
/// <summary>
/// 订阅的消息类型
/// </summary>
public abstract List<MQMessageType> GetSubscribeMessageTypes();
/// <summary>
/// 接收消息自定义处理方法
/// </summary>
/// <param name="messageType">报文消息类型</param>
/// <param name="message">报文Json数据</param>
/// <returns></returns>
public abstract Task OnMessageReceived(MQMessageType messageType, string message);
/// <summary>
/// 接收消息处理方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public async void OnBaseMessageReceived(object sender, BasicDeliverEventArgs e)
{
try
{
var channel = ((IBasicConsumer)sender).Model;
var message = Encoding.UTF8.GetString(e.Body.ToArray());
Console.WriteLine($"接收到消息队列的消息({GetQueueName()}) -> {message}");
Console.WriteLine(Environment.NewLine);
var eventMessage = JsonConvert.DeserializeObject<MQMessageDTO>(message);
var isSubscribe = GetSubscribeMessageTypes().Contains(eventMessage.Type);
if (!string.IsNullOrWhiteSpace(eventMessage.Message) && isSubscribe)
{
await OnMessageReceived(eventMessage.Type, eventMessage.Message);
}
//确认消息消费完毕
channel.BasicAck(e.DeliveryTag, multiple: false);
}
catch (Exception ex)
{
_logger.LogError(ex, $"报文数据入库失败({GetQueueName()})");
Console.WriteLine($"报文数据入库失败({GetQueueName()}):{ex}");
Console.WriteLine(Environment.NewLine);
}
}
/// <summary>
/// 开始监听
/// </summary>
public void StartListenerMessage()
{
new TaskFactory().StartNew(() =>
{
try
{
//rabbitmq 用户名
var userName = _config.GetValue<string>("MQ:UserName");
//rabbitmq 密码
var password = _config.GetValue<string>("MQ:Password");
//rabbitmq 服务地址
var hostName = _config.GetValue<string>("MQ:Host");
//rabbitmq exchange名称
var exchangeName = GetExchangeName();
using (var connection = RabbitMqClientFactory.CeateConnection(userName, password, hostName))
{
using (var channel = connection.CreateModel())
{
//申明交换机
channel.ExchangeDeclare(exchangeName, "fanout", true);
//设置消息发送的数量
var number = GetReceiveMessageNumber();
if (number > 0)
{
channel.BasicQos(0, number, false);
}
//定义队列名称
var queueName = channel.QueueDeclare(GetQueueName(), true, false, false, null).QueueName;
//将消息队列和交换机绑定
channel.QueueBind(queueName, exchangeName, string.Empty);
var consumer = new EventingBasicConsumer(channel);
consumer.Received += OnBaseMessageReceived;
channel.BasicConsume(queueName, false, consumer);
_logger.LogInformation($"---------------------MQ消息队列监听服务启动成功({GetQueueName()})---------------------{Environment.NewLine}");
_manualResetEvent.WaitOne();
}
}
}
catch (Exception ex)
{
_logger.LogError($"MQ Consumer {GetQueueName()} Start Failed", ex);
}
}, TaskCreationOptions.LongRunning);
}
}
}
子类的实现如下:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using JuCheap.Core;
using JuCheap.Models.Enum;
using JuCheap.MQTT.Gather;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace JuCheap.Core.BackMessageService.MQ
{
/// <summary>
/// 流量计实时数据报警处理
/// </summary>
public class RealDataAlarmMQListner : JuCheapMQBaseListner
{
private readonly IServiceScopeFactory _factory;
public RealDataAlarmMQListner(IServiceScopeFactory factory, ILoggerFactory loggerFactory, IConfiguration config) :
base(loggerFactory, config)
{
_factory = factory;
}
/// <summary>
/// 设置队列名称
/// </summary>
/// <returns></returns>
public override string GetQueueName()
{
return "JuCheap_RealDataAlarm";
}
/// <summary>
/// 设置交换机名称
/// </summary>
/// <returns></returns>
public override string GetExchangeName()
{
return MQContants.DeviceExchangeName;
}
/// <summary>
/// 同时处理消息的最大条数
/// </summary>
/// <returns></returns>
public override ushort GetReceiveMessageNumber()
{
return 1;
}
/// <summary>
/// 订阅消息类型
/// </summary>
/// <returns></returns>
public override List<MQMessageType> GetSubscribeMessageTypes()
{
return new List<MQMessageType>
{
MQMessageType.RealData
};
}
/// <summary>
/// 接收消息处理方法
/// </summary>
/// <param name="messageType">消息类型</param>
/// <param name="message">json消息</param>
/// <returns></returns>
public override async Task OnMessageReceived(MQMessageType messageType, string message)
{
using (var scope = _factory.CreateScope())
{
await Task.CompletedTask;
}
}
}
}