添加项目文件。
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace RabbitMQHelper.Attributes
|
||||
{
|
||||
public class RabbitMQAttribute : Attribute
|
||||
{
|
||||
public string Topic { get; set; }
|
||||
|
||||
public RabbitMQAttribute(string topic)
|
||||
{
|
||||
this.Topic = topic;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using RabbitMQHelper.Attributes;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RabbitMQHelper
|
||||
{
|
||||
public class ConsumerExecutorDescriptor
|
||||
{
|
||||
public MethodInfo MethodInfo { get; set; }
|
||||
|
||||
public TypeInfo ImplTypeInfo { get; set; }
|
||||
|
||||
public RabbitMQAttribute Attribute { get; set; }
|
||||
public string ClassName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace RabbitMQHelper.Attributes
|
||||
{
|
||||
public interface IRabbitSubscribe
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RabbitMQHelper
|
||||
{
|
||||
public interface ISendMQMessage
|
||||
{
|
||||
Task<bool> Send(string topic, object value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using EasyNetQ;
|
||||
using EasyNetQ.Topology;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace RabbitMQHelper
|
||||
{
|
||||
public static class InitRabbitMQSetup
|
||||
{
|
||||
public static void AddInitMQ(this IServiceCollection services, Action<RabbitConfig> setupAction, ILogger logger = null)
|
||||
{
|
||||
//#if NET5_0
|
||||
services.AddHttpContextAccessor();//<IHttpContextAccessor, HttpContextAccessor>();
|
||||
//#endif
|
||||
|
||||
var options = new RabbitConfig();
|
||||
setupAction(options);
|
||||
try
|
||||
{
|
||||
var bus = RabbitHutch.CreateBus($"host={options.Host};virtualHost={options.VirtualHost};username={options.UserName};password={options.Password}");
|
||||
bus.Advanced.Connected += delegate (object sender1, ConnectedEventArgs e1) { c_Conneted(sender1, e1, logger); };
|
||||
bus.Advanced.Disconnected += delegate (object sender1, DisconnectedEventArgs e1) { c_DisConnect(sender1, e1, logger); };
|
||||
services.AddSingleton<IBus>(bus);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("MQ初始化异常:" + ex.Message);
|
||||
}
|
||||
services.AddSingleton<IRabbitConfig>(sp => options);
|
||||
services.AddScoped<ISendMQMessage, SendMQMessage>();
|
||||
services.AddHostedService<MQHostedService>();
|
||||
|
||||
if (options.ListSubscribe != null)
|
||||
{
|
||||
foreach (var item in options.ListSubscribe)
|
||||
{
|
||||
if (options.DefaultRegisterWay.ToLower() == "singleton")
|
||||
{
|
||||
services.TryAddSingleton(item);
|
||||
}
|
||||
else if (options.DefaultRegisterWay.ToLower() == "scoped")
|
||||
{
|
||||
services.TryAddScoped(item);
|
||||
}
|
||||
else if (options.DefaultRegisterWay.ToLower() == "transient")
|
||||
{
|
||||
services.TryAddTransient(item);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
services.TryAddSingleton(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static void c_Conneted(object sender, EventArgs e, ILogger logger)
|
||||
{
|
||||
if (logger == null)
|
||||
{
|
||||
Console.WriteLine("RabbitMQ已链接");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
static void c_DisConnect(object sender, EventArgs e, ILogger logger)
|
||||
{
|
||||
if (logger == null)
|
||||
{
|
||||
Console.WriteLine("RabbitMQ已断开");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
using EasyNetQ;
|
||||
using EasyNetQ.Topology;
|
||||
using RabbitMQHelper.Attributes;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using RabbitMQHelper.Models;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace RabbitMQHelper
|
||||
{
|
||||
public class MQHostedService : BackgroundService
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IBus _bus;
|
||||
private readonly IRabbitConfig _mongoDBConfig;
|
||||
private readonly IMongoCollection<ReceiveRecord> _collection;
|
||||
private static readonly object lockHelper = new object();
|
||||
public MQHostedService(IServiceProvider serviceProvider, IBus bus, IRabbitConfig mongoDBConfig)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_bus = bus;
|
||||
_mongoDBConfig = mongoDBConfig;
|
||||
var database = new MongoClient(_mongoDBConfig.MongoConnectionString).GetDatabase(_mongoDBConfig.MongoDatabaseName);
|
||||
_collection = database.GetCollection<ReceiveRecord>("mq_receive_record");
|
||||
}
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
var executorDescriptorList = new List<ConsumerExecutorDescriptor>();
|
||||
foreach (Type ty in _mongoDBConfig.ListSubscribe)
|
||||
{
|
||||
executorDescriptorList.AddRange(GetTopicAttributesDescription(ty.GetTypeInfo()));
|
||||
}
|
||||
|
||||
|
||||
var exchange = await _bus.Advanced.ExchangeDeclareAsync(_mongoDBConfig.DefaultExchange, ExchangeType.Topic);
|
||||
|
||||
foreach (var item in executorDescriptorList)
|
||||
{
|
||||
using (var scope = _serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
|
||||
{
|
||||
var topic = item.Attribute.Topic;
|
||||
var provider = scope.ServiceProvider;
|
||||
var obj = ActivatorUtilities.GetServiceOrCreateInstance(provider, item.ImplTypeInfo.GetTypeInfo());
|
||||
|
||||
var subscriptId = $"{ item.ClassName.ToLower() }.{item.MethodInfo.Name.ToLower()}";
|
||||
|
||||
var queue = await _bus.Advanced.QueueDeclareAsync(subscriptId);
|
||||
|
||||
await _bus.Advanced.BindAsync(exchange, queue, topic, null);
|
||||
|
||||
_bus.Advanced.Consume<RabbitMessage>(queue, (msg, info) => Task.Factory.StartNew(async () =>
|
||||
{
|
||||
await ReceiveMessage(msg.Body, info.Queue, info.RoutingKey);
|
||||
lock (lockHelper)
|
||||
{
|
||||
object[] parameters = new object[] { msg.Body.Data, msg.Body.Headers };
|
||||
item.MethodInfo.Invoke(obj, parameters);
|
||||
}
|
||||
}));
|
||||
|
||||
//await _bus.PubSub.SubscribeAsync<RabbitMessage>(subscriptId, async msg =>
|
||||
//{
|
||||
// await ReceiveMessage(msg, subscriptId, topic);
|
||||
// object[] parameters = new object[] { msg.Data, msg.Headers };
|
||||
// item.MethodInfo.Invoke(obj, parameters);
|
||||
|
||||
//}, x => x.WithTopic(topic).w);
|
||||
}
|
||||
}
|
||||
await Task.Delay(Timeout.Infinite, stoppingToken);
|
||||
}
|
||||
public async Task ReceiveMessage(RabbitMessage msg,string subscriptId,string topic)
|
||||
{
|
||||
try {
|
||||
//var database = new MongoClient(_mongoDBConfig.MongoConnectionString).GetDatabase(_mongoDBConfig.MongoDatabaseName);
|
||||
//var collection = database.GetCollection<ReceiveRecord>("mq_receive_record");
|
||||
await _collection.InsertOneAsync(new ReceiveRecord(msg.RecordId, subscriptId, topic));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
private IEnumerable<ConsumerExecutorDescriptor> GetTopicAttributesDescription(TypeInfo typeInfo)
|
||||
{
|
||||
foreach (var method in typeInfo.DeclaredMethods)
|
||||
{
|
||||
var topicAttr = method.GetCustomAttributes<RabbitMQAttribute>(true);
|
||||
var topicAttributes = topicAttr as IList<RabbitMQAttribute> ?? topicAttr.ToList();
|
||||
|
||||
if (!topicAttributes.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var attr in topicAttributes)
|
||||
{
|
||||
yield return InitDescriptor(attr, method, typeInfo, typeInfo.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
private ConsumerExecutorDescriptor InitDescriptor(RabbitMQAttribute attr, MethodInfo methodInfo, TypeInfo implType, string name)
|
||||
{
|
||||
var descriptor = new ConsumerExecutorDescriptor
|
||||
{
|
||||
Attribute = attr,
|
||||
MethodInfo = methodInfo,
|
||||
ImplTypeInfo = implType,
|
||||
ClassName = name
|
||||
};
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
|
||||
|
||||
namespace RabbitMQHelper.Models
|
||||
{
|
||||
public class PublishRecord
|
||||
{
|
||||
public PublishRecord(string publishId, string topic,object message,bool success)
|
||||
{
|
||||
this.PublishId = publishId;
|
||||
this.Topic = topic;
|
||||
this.MessageContent = message;
|
||||
this.Success = success;
|
||||
}
|
||||
public string id { get; set; } = Guid.NewGuid().ToString("N");
|
||||
public string PublishId { get; set; }
|
||||
public string Topic { get; set; }
|
||||
public object MessageContent { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public DateTime PublishTime { get; set; } = DateTime.Now;
|
||||
}
|
||||
|
||||
public class ReceiveRecord
|
||||
{
|
||||
public ReceiveRecord(string publishId, string subscriptId, string topic)
|
||||
{
|
||||
this.PublishId = publishId;
|
||||
this.SubscriptId = subscriptId;
|
||||
this.Topic = topic;
|
||||
}
|
||||
|
||||
public string id { get; set; } = Guid.NewGuid().ToString("N");
|
||||
public string PublishId { get; set; }
|
||||
public string SubscriptId { get; set; }
|
||||
public string Topic { get; set; }
|
||||
public DateTime ReceiveTime { get; set; } = DateTime.Now;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:60480/",
|
||||
"sslPort": 44373
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"RabbitMQHelper": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:5001;http://localhost:5000"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace RabbitMQHelper
|
||||
{
|
||||
public interface IRabbitConfig
|
||||
{
|
||||
string Host { get; set; }
|
||||
string VirtualHost { get; set; }
|
||||
string UserName { get; set; }
|
||||
string Password { get; set; }
|
||||
List<Type> ListSubscribe { get; set; }
|
||||
string MongoDatabaseName { get; set; }
|
||||
string MongoConnectionString { get; set; }
|
||||
string DefaultExchange { get; set; }
|
||||
|
||||
string DefaultRegisterWay { get; set; }
|
||||
}
|
||||
public class RabbitConfig: IRabbitConfig
|
||||
{
|
||||
public string Host { get; set; } = "49.233.122.91";
|
||||
public string VirtualHost { get; set; } = "/";
|
||||
public string UserName { get; set; } = "guest";
|
||||
public string Password { get; set; } = "guest";
|
||||
public List<Type> ListSubscribe { get; set; }
|
||||
public string MongoDatabaseName { get; set; }
|
||||
public string MongoConnectionString { get; set; }
|
||||
public string DefaultExchange { get; set; } = "hscw.default.topic";
|
||||
|
||||
|
||||
public string DefaultRegisterWay { get; set; } = "singleton";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNetCore.CAP" Version="8.3.4" />
|
||||
<PackageReference Include="EasyNetQ" Version="7.8.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.4" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="3.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace RabbitMQHelper
|
||||
{
|
||||
public class RabbitMessage
|
||||
{
|
||||
public RabbitMessage(object data, Dictionary<string, string> headers = null)
|
||||
{
|
||||
this.Data = data;
|
||||
this.Headers = headers;
|
||||
}
|
||||
public string RecordId { get; set; } = Guid.NewGuid().ToString("N");
|
||||
public object Data { get; set; }
|
||||
public Dictionary<string,string> Headers { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using EasyNetQ;
|
||||
using EasyNetQ.Topology;
|
||||
using RabbitMQHelper.Models;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace RabbitMQHelper
|
||||
{
|
||||
public class SendMQMessage:ISendMQMessage
|
||||
{
|
||||
private readonly IBus _bus;
|
||||
private readonly ILogger<SendMQMessage> _logger;
|
||||
private readonly IRabbitConfig _mongoDBConfig;
|
||||
private readonly IMongoCollection<PublishRecord> _collection;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public SendMQMessage(IBus bus, ILogger<SendMQMessage> logger, IRabbitConfig mongoDBConfig, IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_bus = bus;
|
||||
_logger = logger;
|
||||
_mongoDBConfig = mongoDBConfig;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
var database = new MongoClient(_mongoDBConfig.MongoConnectionString).GetDatabase(_mongoDBConfig.MongoDatabaseName);
|
||||
_collection = database.GetCollection<PublishRecord>("mq_publish_record");
|
||||
}
|
||||
public async Task<bool> Send(string topic, object value)
|
||||
{
|
||||
if (!_bus.Advanced.IsConnected)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
Dictionary<string, string> headers = new Dictionary<string, string>();
|
||||
|
||||
if (_httpContextAccessor.HttpContext != null && _httpContextAccessor.HttpContext.Request != null && _httpContextAccessor.HttpContext.Request.Headers != null)
|
||||
{
|
||||
if (_httpContextAccessor.HttpContext.Request.Headers.ContainsKey("token"))
|
||||
{
|
||||
headers.Add("token", _httpContextAccessor.HttpContext.Request.Headers["token"].ToString() ?? "");
|
||||
}
|
||||
|
||||
;
|
||||
}
|
||||
bool success = false;
|
||||
|
||||
var model = new RabbitMessage(value, headers);
|
||||
|
||||
var exchange = await _bus.Advanced.ExchangeDeclareAsync(_mongoDBConfig.DefaultExchange, ExchangeType.Topic);
|
||||
|
||||
var message = new Message<RabbitMessage>(model);
|
||||
await _bus.Advanced.PublishAsync<RabbitMessage>(exchange, topic, false, message).ContinueWith(m =>
|
||||
{
|
||||
if (m.IsCompleted && m.IsCompletedSuccessfully)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError(m.Exception, "RabbitMQ消息推送失败 topic={Topic}", topic);
|
||||
}
|
||||
});
|
||||
try
|
||||
{
|
||||
await _collection.InsertOneAsync(new PublishRecord(model.RecordId, topic, value, success));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "RabbitMQ推送记录写入异常 topic={Topic}", topic);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user