210 lines
8.9 KiB
C#
210 lines
8.9 KiB
C#
using System.Diagnostics;
|
||
using System.Net;
|
||
using DotNetCore.CAP;
|
||
using DotNetCore.CAP.Internal;
|
||
using DotNetCore.CAP.Messages;
|
||
using Fake;
|
||
using Fake.EventBus.RabbitMQ;
|
||
using Fake.Modularity;
|
||
using Fake.ObjectMapping.AutoMapper;
|
||
using Fake.ObjectStorage;
|
||
using Fake.RabbitMQ;
|
||
using FreeRedis;
|
||
using Hangfire;
|
||
using Hangfire.Redis.StackExchange;
|
||
using InterfaceForward.Domain.Shared.Helpers;
|
||
using Microsoft.Extensions.Configuration;
|
||
using Microsoft.Extensions.Logging;
|
||
using RabbitMQ.Client;
|
||
using Savorboard.CAP.InMemoryMessageQueue;
|
||
using TrackCenter.Application.Kafka;
|
||
using TrackCenter.Application.CAP;
|
||
using TrackCenter.Application.HostServices;
|
||
using TrackCenter.Application.Options;
|
||
using TrackCenter.Application.Rabbit;
|
||
|
||
namespace TrackCenter.Application;
|
||
|
||
[DependsOn(typeof(FakeRabbitMqModule))]
|
||
[DependsOn(typeof(FakeObjectMappingAutoMapperModule))]
|
||
[DependsOn(typeof(FakeEventBusRabbitMqModule))]
|
||
[DependsOn(typeof(FakeObjectStorageTencentCosModule))]
|
||
[DependsOn(typeof(TrackCenterDomainModule))]
|
||
public class TrackCenterApplicationModule : FakeModule
|
||
{
|
||
public override void ConfigureServices(ServiceConfigurationContext context)
|
||
{
|
||
var configuration = context.Services.GetConfiguration();
|
||
|
||
context.Services.Configure<FakeAutoMapperOptions>(options =>
|
||
{
|
||
options.ScanProfiles<TrackCenterApplicationModule>();
|
||
});
|
||
|
||
var rabbitOptions = configuration.GetSection("RabbitMQ").Get<FakeRabbitMqOptions>()!.Default;
|
||
|
||
#region CAP
|
||
|
||
context.Services.AddSingleton<ISubscribeExecutor, MySubscribeExecutor>();
|
||
if (!Debugger.IsAttached)
|
||
{
|
||
context.Services.AddCap(options =>
|
||
{
|
||
options.UseMySql(configuration["ConnectionStrings:Default"]!);
|
||
options.UseRabbitMQ(configure =>
|
||
{
|
||
configure.HostName = rabbitOptions.HostName;
|
||
configure.UserName = rabbitOptions.UserName;
|
||
configure.Password = rabbitOptions.Password;
|
||
configure.Port = rabbitOptions.Port;
|
||
configure.BasicQosOptions =
|
||
new RabbitMQOptions.BasicQos(configuration.GetValue<ushort>("CAP:PrefetchCount"));
|
||
});
|
||
options.FailedRetryInterval = configuration.GetValue<int>("CAP:FailedRetryInterval");
|
||
options.FailedRetryCount = configuration.GetValue<int>("CAP:FailedRetryCount");
|
||
options.SucceedMessageExpiredAfter = configuration.GetValue<int>("CAP:SucceedMessageExpiredAfter");
|
||
options.FallbackWindowLookbackSeconds =
|
||
configuration.GetValue<int>("CAP:FallbackWindowLookbackSeconds");
|
||
|
||
options.UseDashboard(dashboardOptions => { dashboardOptions.PathBase = configuration["ASPNETCORE_PATHBASE"]; });
|
||
options.FailedThresholdCallback = faileCalback =>
|
||
{
|
||
try
|
||
{
|
||
Log.Error($@"
|
||
|-CAP失败回调事件:
|
||
|-处理类型:{(faileCalback.MessageType == MessageType.Subscribe ? "消费消息达到最大重试次数,需要开发人员介入" : "生产消息推送失败")}
|
||
|-头部信息:{faileCalback.Message.Headers.ToJson()}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error("【严重】CAP失败回调事件发生未处理异常" + ex);
|
||
}
|
||
};
|
||
}).AddSubscribeFilter<CapFilter>();
|
||
}
|
||
else
|
||
{
|
||
//是本地调试环境,用内存存储和内存队列
|
||
context.Services.AddCap(capOptions =>
|
||
{
|
||
capOptions.UseInMemoryStorage();
|
||
capOptions.UseInMemoryMessageQueue();
|
||
capOptions.UseDashboard();
|
||
}).AddSubscribeFilter<CapFilter>();
|
||
context.Services.GetInitLogger<TrackCenterApplicationModule>().LogInformation("-- 当前为本地环境,用内存存储和内存队列");
|
||
}
|
||
|
||
#endregion
|
||
|
||
var redisOptions = configuration.GetSection("Redis").Get<ConnectionStringBuilder>();
|
||
if (redisOptions == null)
|
||
throw new FakeException("未找到Redis相关配置,请检查配置文件中是否包含名为Redis的节点");
|
||
RedisHelper.Init(redisOptions, showLogInfo: Debugger.IsAttached);
|
||
|
||
context.Services.AddHostedService<RabbitClient>();
|
||
context.Services.Configure<RabbitOptions>(options =>
|
||
{
|
||
options.Declarations = new List<Action<IDeclaration>>()
|
||
{
|
||
o => o.ExchangeDeclare(GlobalConst.TrackChangeExchange, ExchangeType.Topic, true),
|
||
o => o.ExchangeDeclare(GlobalConst.TrackPushExchange, ExchangeType.Topic, true)
|
||
};
|
||
options.Consumes = new List<ConsumeOptions>
|
||
{
|
||
new()
|
||
{
|
||
Queue = GlobalConst.TrackRefreshSubscribe,
|
||
FetchCount = configuration.GetValue<ushort>("TrackApp:TrackRefreshFetchCount"),
|
||
FailedRequeue = false,
|
||
Declaration = o =>
|
||
{
|
||
o.ExchangeDeclare(GlobalConst.InterfaceRelayExchange, ExchangeType.Direct, true);
|
||
o.QueueDeclare(GlobalConst.TrackRefreshSubscribe, true);
|
||
o.QueueBind(GlobalConst.TrackRefreshSubscribe, GlobalConst.InterfaceRelayExchange,
|
||
GlobalConst.TrackRefreshSubscribe);
|
||
}
|
||
},
|
||
new()
|
||
{
|
||
Queue = GlobalConst.TrackPushCompletedSubscribe,
|
||
FetchCount = configuration.GetValue<ushort>("TrackApp:TrackRefreshFetchCount"),
|
||
FailedRequeue = false,
|
||
Declaration = o =>
|
||
{
|
||
o.ExchangeDeclare(GlobalConst.InterfaceRelayExchange, ExchangeType.Direct, true);
|
||
o.QueueDeclare(GlobalConst.TrackPushCompletedSubscribe, true);
|
||
o.QueueBind(GlobalConst.TrackPushCompletedSubscribe, GlobalConst.InterfaceRelayExchange,
|
||
GlobalConst.TrackPushCompletedSubscribe);
|
||
}
|
||
}
|
||
};
|
||
});
|
||
|
||
context.Services.Configure<TrackAppOptions>(configuration.GetSection("TrackApp"));
|
||
context.Services.Configure<InterfaceRelayParamsConfigOptions>(
|
||
configuration.GetSection("InterfaceRelayParamsConfig"));
|
||
|
||
var connectionString = $"{configuration["Redis:Host"]}" +
|
||
$",password={configuration["Redis:Password"]}" +
|
||
$",defaultDatabase={configuration["Redis:Database"]}" +
|
||
$",abortConnect=false";
|
||
|
||
// 注册预警计算服务
|
||
context.Services.AddWarningCalcServices(configuration);
|
||
|
||
// 注册预警任务后台服务
|
||
context.Services.AddHostedService<WarningTaskComponentHostedService>();
|
||
|
||
// 注册飞书服务(用于预警通知)
|
||
context.Services.AddFeishuNetSdk(o =>
|
||
{
|
||
o.AppId = configuration.GetValue<string>("FeiShu:AppId")!;
|
||
o.AppSecret = configuration.GetValue<string>("FeiShu:AppSecret")!;
|
||
o.EnableLogging = configuration.GetValue<bool>("FeiShu:EnableLogging");
|
||
});
|
||
|
||
// 注册HangFire服务
|
||
context.Services.Configure<TrackWarningTaskOptions>(configuration.GetSection("WarningTask"));
|
||
context.Services.AddHangfire(o =>
|
||
{
|
||
var options = new RedisStorageOptions
|
||
{
|
||
Prefix = $"{GlobalConst.TrackHangfireKeyPrefix}:",
|
||
Db = int.Parse(configuration["Redis:Database"]!),
|
||
};
|
||
o.UseRedisStorage(connectionString, options)
|
||
.WithJobExpirationTimeout(TimeSpan.FromHours(1)); // 终止态任务只保留1小时
|
||
});
|
||
var hangfireWorkerCount = configuration.GetValue<int>("TrackApp:HangfireWorkerCount");
|
||
if (hangfireWorkerCount <= 0)
|
||
{
|
||
hangfireWorkerCount = Math.Max(4, Environment.ProcessorCount);
|
||
}
|
||
|
||
context.Services.AddHangfireServer(o =>
|
||
{
|
||
// 索引越小优先级越高
|
||
o.Queues =
|
||
[
|
||
GlobalConst.WarningJobQueueLevel0,
|
||
GlobalConst.WarningJobQueueLevel1,
|
||
GlobalConst.WarningJobQueueLevel2,
|
||
"default"
|
||
];
|
||
o.ServerName = Dns.GetHostName();
|
||
o.ShutdownTimeout = TimeSpan.FromSeconds(10);
|
||
o.WorkerCount = hangfireWorkerCount;
|
||
});
|
||
|
||
// 注册轨迹业务定时任务服务
|
||
context.Services.AddHostedService<TrackTaskComponentHostedService>();
|
||
|
||
context.Services.AddHttpClient("itfx", client =>
|
||
{
|
||
client.Timeout = TimeSpan.FromSeconds(20);
|
||
client.BaseAddress = new Uri(configuration["TrackApp:ItfxBaseAddress"]!);
|
||
});
|
||
}
|
||
}
|