using BuildFlow.Host; using BuildFlow.Host.Configuration; using OpenTelemetry.Logs; using Winton.Extensions.Configuration.Consul; var builder = WebApplication.CreateBuilder(args); // 敏感配置(连接串/密钥)从本地 appsettings.Secrets.json 覆盖,该文件不入库(见 .gitignore)。 // 不存在时 optional:true 静默跳过,回退到 appsettings.json 中的占位符。 builder.Configuration.AddJsonFile("appsettings.Secrets.json", optional: true, reloadOnChange: true); // Consul KV 配置中心(优先级最高,覆盖本地 json + secrets,作为生产配置真相源)。 // 加载顺序决定优先级:后注册的覆盖先注册的,故 Consul 在 Secrets 之后。 // 鸡生蛋问题:Consul 地址本身用环境变量 Consul__Host 注入(compose 配置), // 默认回退到 middleware 公网地址。Consul 不可用时 Optional=true 回退本地 json,不阻断启动。 var consulHost = builder.Configuration["Consul:Host"] ?? "http://43.134.235.58:8520"; var consulToken = builder.Configuration["Consul:Token"] ?? ""; builder.Configuration.AddConsul( "buildflow/", options => { options.ConsulConfigurationOptions = co => { co.Address = new Uri(consulHost); // ACL token:Consul 开启了 ACL(default deny),api 必须带专用 token 才能读写 KV // token 通过环境变量 Consul:Token 注入(compose),不进代码/镜像 if (!string.IsNullOrEmpty(consulToken)) co.Token = consulToken; }; options.Optional = true; // Consul 不可用不阻断启动,回退本地 appsettings options.ReloadOnChange = true; // KV 变更自动刷新 IConfiguration(热重载基础) options.OnLoadException = ex => ex.Ignore = true; // 容错:Consul 抖动不影响应用 }); // OTel 日志导出 var otlpEndpoint = builder.Configuration["OpenTelemetry:OtlpEndpoint"] ?? "http://localhost:4316"; builder.Logging.AddOpenTelemetry(logging => { logging.AddOtlpExporter(options => options.Endpoint = new Uri(otlpEndpoint)); }); // ABP 模块化引导: // 1) 注册 ObjectAccessor,打通 ABP 模块与 ASP.NET Core 管线(模块内 MapHub/UseMiddleware 依赖) // 2) 按 [DependsOn] 加载 platform/rag/file/im/workflow 各模块的 Application/Infrastructure 层 builder.Services.AddHostObjectAccessors(); await builder.AddApplicationAsync(); var app = builder.Build(); await app.InitializeApplicationAsync(); // 启动期数据库初始化:迁移各库 + IM MongoDB 建索引 + 种子数据(单库失败不影响其他库) await DatabaseInitializer.RunAsync(app.Services); await app.RunAsync();