using System.Net; using BSI.Stack.Rabbit; using DotNetCore.CAP; using DotNetCore.CAP.Internal; using Hangfire; using Hangfire.Redis.StackExchange; using Microsoft.Extensions.Configuration; using RabbitMQ.Client; using Savorboard.CAP.InMemoryMessageQueue; using SJZY.Expand.ABP.Core.Localization; using SJZY.Expand.ABP.Core.Logger; using SJZY.Expand.ABP.Core.PublicMethords; using SJZY.Expand.AliyunOSS; using SJZY.InterfaceRelay.Application.Contracts; using SJZY.Track.Application.CAP; using SJZY.Track.Application.Contract; using SJZY.Track.Application.Hangfire; using SJZY.Track.Application.Kafka; using SJZY.Track.Application.Localization; using SJZY.Track.Application.Options; using SJZY.Track.Application.Track2InterfaceRelay; using SJZY.UserCenter.Contracts; using SJZY.UserCenter.SharedModel; using SJZY.UserCenter.SharedModel.Pub; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AutoMapper; using Volo.Abp.FluentValidation; using Volo.Abp.Http.Client; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.VirtualFileSystem; namespace SJZY.Track.Application; [DependsOn( typeof(AbpAutoMapperModule), typeof(AbpFluentValidationModule), typeof(AbpLocalizationModule), typeof(AbpVirtualFileSystemModule), typeof(AbpHttpClientModule), typeof(SjzyUserCenterHttpApiModule), typeof(SJZYInterfaceRelayApplicationContractsModule), typeof(SjzyTrackDomainModule), typeof(SjzyTrackApplicationContractModule) )] public class SjzyTrackApplicationModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { var configuration = context.Services.GetConfiguration(); Configure(options => { options.AddMaps(true); }); Configure(options => { options.ConventionalControllers.Create(typeof(SjzyTrackApplicationModule).Assembly); //创建动态api }); //添加虚拟文件系统 Configure(options => { options.FileSets.AddEmbedded("SJZY.Track.Application"); }); //添加多语言 var languageConfig = configuration.GetSection("Language"); Configure(options => { options.Resources .Add("zh") .AddBaseTypes(typeof(SjzyBasicLocalization)) .AddRedisResource(languageConfig) .AddVirtualJson("/Localization/Resources"); }); //授权拦截提示 context.Services.Configure(options => { options.Filters.Add(new ApiAsyncAuthorizationFilter()); }); //用户中心 context.Services.AddHttpClientProxies(typeof(SjzyUserCenterHttpApiModule).Assembly, "UserCenter", false); // 接口通 context.Services.Configure(configuration.GetSection("Track2InterfaceRelay")); context.Services.AddHttpClient("InterfaceForward") .AddHttpMessageHandler(); context.Services.AddHttpClientProxies(typeof(SJZYInterfaceRelayApplicationContractsModule).Assembly, "InterfaceForward", false ); //CAP context.Services.AddSingleton(); context.Services.AddCapTableNameService(); if (!System.Diagnostics.Debugger.IsAttached) { context.Services.AddCap(options => { options.UseMySql(configuration["ConnectionStrings:DefaultConnection"]!); options.UseRabbitMQ(configure => { configure.HostName = configuration["RabbitMQ:HostName"]!; configure.UserName = configuration["RabbitMQ:UserName"]!; configure.Password = configuration["RabbitMQ:Password"]!; configure.Port = configuration.GetValue("RabbitMQ:Port"); configure.BasicQosOptions = new RabbitMQOptions.BasicQos(configuration.GetValue("CAP:PrefetchCount")); }); options.FailedRetryInterval = configuration.GetValue("CAP:FailedRetryInterval"); options.FailedRetryCount = configuration.GetValue("CAP:FailedRetryCount"); options.SucceedMessageExpiredAfter = configuration.GetValue("CAP:SucceedMessageExpiredAfter"); options.FallbackWindowLookbackSeconds = configuration.GetValue("CAP:FallbackWindowLookbackSeconds"); options.UseDashboard(dashboardOptions => { dashboardOptions.PathBase = System.Diagnostics.Debugger.IsAttached ? "" : configuration["Swagger:JsonUrlPrefix"]!; }); options.FailedThresholdCallback = faileCalback => { try { LogHelper.Error($@" |-CAP失败回调事件: |-处理类型:{(faileCalback.MessageType == DotNetCore.CAP.Messages.MessageType.Subscribe ? "消费消息达到最大重试次数,需要开发人员介入" : "生产消息推送失败")} |-头部信息:{faileCalback.Message.Headers.ToJson()}"); } catch (Exception ex) { LogHelper.Error("【严重】CAP失败回调事件发生未处理异常" + ex); } }; }).AddSubscribeFilter(); } else { //是本地调试环境,用内存存储和内存队列 context.Services.AddCap(capOptions => { capOptions.UseInMemoryStorage(); capOptions.UseInMemoryMessageQueue(); capOptions.UseDashboard(); }).AddSubscribeFilter(); Console.WriteLine("-- 当前为VS本地环境,用内存存储和内存队列"); } context.Services.AddRabbitBoot(options => { options.ConnectionString = $"amqp://{configuration["RabbitMQ:UserName"]}:{configuration["RabbitMQ:Password"]}@{configuration["RabbitMQ:HostName"]}:{configuration["RabbitMQ:Port"]}"; options.PoolSize = configuration.GetValue("RabbitMQ:PoolSize"); options.Declarations = new List>() { o => o.ExchangeDeclare(GlobalConst.TrackChangeExchange, ExchangeType.Topic, true), o => o.ExchangeDeclare(GlobalConst.TrackPushExchange, ExchangeType.Topic, true) }; options.Consumes = new List { new() { Queue = GlobalConst.TrackRefreshSubscribe, FetchCount = configuration.GetValue("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("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); } } }; }, typeof(SjzyTrackApplicationModule).Assembly); context.Services.Configure(configuration.GetSection("TrackApp")); context.Services.Configure( configuration.GetSection("InterfaceRelayParamsConfig")); //注册阿里云OSS服务 context.Services.AddAliOSS(option => { option.AccessKeyId = configuration["OSS:AccessKeyId"]; option.AccessKeySecret = configuration["OSS:AccessKeySecret"]; option.Endpoint = configuration["OSS:Endpoint"]; option.BucketName = configuration["OSS:BucketName"]; option.ReturnHttpsUrl = true; }); var connectionString = $"{configuration["Redis:Host"]}" + $",password={configuration["Redis:Password"]}" + $",defaultDatabase={configuration["Redis:Database"]}" + $",abortConnect=false"; // 注册预警计算服务 //context.Services.AddWarningCalcServices(configuration); // 注册预警任务后台服务 context.Services.AddHostedService(); // 注册HangFire服务 context.Services.Configure(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小时 }); context.Services.AddHangfireServer(o => { // 索引越小优先级越高 o.Queues = new[] { GlobalConst.WarningJobQueueLevel0, GlobalConst.WarningJobQueueLevel1, GlobalConst.WarningJobQueueLevel2, "default" }; o.ServerName = Dns.GetHostName(); o.ShutdownTimeout = TimeSpan.FromSeconds(10); o.WorkerCount = 1; }); } public override void PreConfigureServices(ServiceConfigurationContext context) { PreConfigure(options => { options.ProxyClientActions.Add((_, _, httpClient) => { //如果设置Token,前端需要传入Token 否则引发异常 httpClient.SetTokenHeader(); httpClient.Timeout = TimeSpan.FromMinutes(3); }); }); } }