track/src/TrackCenter.Application/TrackCenterApplicationModule.cs
xiaolipro d21149a973
All checks were successful
Build and Deploy / deploy (push) Successful in 52s
..
2026-09-28 09:40:00 +08:00

210 lines
8.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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"]!);
});
}
}