diff --git a/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Program.cs b/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Program.cs index 7701e7c19..5199f77e0 100644 --- a/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Program.cs +++ b/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Program.cs @@ -54,6 +54,8 @@ public class Program catch (Exception ex) { Log.Fatal(ex, "Host terminated unexpectedly!"); + Console.WriteLine("Host terminated unexpectedly!"); + Console.WriteLine(ex.ToString()); return 1; } finally diff --git a/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Program.cs b/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Program.cs index f95eed159..586f3a5d5 100644 --- a/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Program.cs +++ b/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Program.cs @@ -54,6 +54,8 @@ public class Program catch (Exception ex) { Log.Fatal(ex, "Host terminated unexpectedly!"); + Console.WriteLine("Host terminated unexpectedly!"); + Console.WriteLine(ex.ToString()); return 1; } finally diff --git a/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Program.cs b/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Program.cs index a4f3d9e66..fbdc023ef 100644 --- a/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Program.cs +++ b/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Program.cs @@ -54,6 +54,8 @@ public class Program catch (Exception ex) { Log.Fatal(ex, "Host terminated unexpectedly!"); + Console.WriteLine("Host terminated unexpectedly!"); + Console.WriteLine(ex.ToString()); return 1; } finally diff --git a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Program.cs b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Program.cs index e86bcff5b..774932a42 100644 --- a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Program.cs +++ b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Program.cs @@ -54,6 +54,8 @@ public class Program catch (Exception ex) { Log.Fatal(ex, "Host terminated unexpectedly!"); + Console.WriteLine("Host terminated unexpectedly!"); + Console.WriteLine(ex.ToString()); return 1; } finally diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Program.cs b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Program.cs index 971d2ee84..5f8744aa5 100644 --- a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Program.cs +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Program.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Serilog; +using System; using System.IO; using System.Threading.Tasks; using Volo.Abp.IO; @@ -50,6 +51,13 @@ public class Program await app.RunAsync(); return 0; } + catch (Exception ex) + { + Log.Fatal(ex, "Host terminated unexpectedly!"); + Console.WriteLine("Host terminated unexpectedly!"); + Console.WriteLine(ex.ToString()); + return 1; + } finally { Log.CloseAndFlush(); diff --git a/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Program.cs b/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Program.cs index d08309c96..6bda4f62e 100644 --- a/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Program.cs +++ b/aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Program.cs @@ -54,6 +54,8 @@ public class Program catch (Exception ex) { Log.Fatal(ex, "Host terminated unexpectedly!"); + Console.WriteLine("Host terminated unexpectedly!"); + Console.WriteLine(ex.ToString()); return 1; } finally diff --git a/aspnet-core/services/LY.MicroService.identityServer/Program.cs b/aspnet-core/services/LY.MicroService.identityServer/Program.cs index 4e1978cd7..4216803ad 100644 --- a/aspnet-core/services/LY.MicroService.identityServer/Program.cs +++ b/aspnet-core/services/LY.MicroService.identityServer/Program.cs @@ -54,6 +54,8 @@ public class Program catch (Exception ex) { Log.Fatal(ex, "Host terminated unexpectedly!"); + Console.WriteLine("Host terminated unexpectedly!"); + Console.WriteLine(ex.ToString()); return 1; } finally diff --git a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/InternalApiGatewayOptions.cs b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/InternalApiGatewayOptions.cs index c8cbecebc..812b2f3e4 100644 --- a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/InternalApiGatewayOptions.cs +++ b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/InternalApiGatewayOptions.cs @@ -4,9 +4,14 @@ namespace LINGYUN.MicroService.Internal.ApiGateway { public class InternalApiGatewayOptions { + /// + /// 聚合异常时是否忽略 + /// + public bool AggregationIgnoreError { get; set; } public DownstreamOpenApi[] DownstreamOpenApis { get; set; } public InternalApiGatewayOptions() { + AggregationIgnoreError = true; DownstreamOpenApis = new DownstreamOpenApi[0]; } } diff --git a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Ocelot/Multiplexer/AbpResponseMergeAggregator.cs b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Ocelot/Multiplexer/AbpResponseMergeAggregator.cs index fb2b3665c..d40f85925 100644 --- a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Ocelot/Multiplexer/AbpResponseMergeAggregator.cs +++ b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Ocelot/Multiplexer/AbpResponseMergeAggregator.cs @@ -1,4 +1,8 @@ -using Microsoft.AspNetCore.Http; +using LINGYUN.MicroService.Internal.ApiGateway; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Ocelot.Middleware; @@ -14,6 +18,17 @@ namespace Ocelot.Multiplexer { public class AbpResponseMergeAggregator : IDefinedAggregator { + public ILogger Logger { protected get; set; } + protected InternalApiGatewayOptions Options { get; } + + public AbpResponseMergeAggregator( + IOptions options) + { + Options = options.Value; + + Logger = NullLogger.Instance; + } + public async Task Aggregate(List responses) { return await MapAbpApiDefinitionAggregateContentAsync(responses); @@ -29,7 +44,41 @@ namespace Ocelot.Multiplexer }; foreach (var httpResponse in responses) { - var content = await httpResponse.Items.DownstreamResponse().Content.ReadAsStringAsync(); + var errorItems = httpResponse.Items.Errors(); + var response = httpResponse.Items.DownstreamResponse(); + + if (errorItems.Any()) + { + if (!Options.AggregationIgnoreError) + { + var errorItem = errorItems.First(); + string error = errorItems.Select(x => x.Message).JoinAsString(";"); + if (httpResponse.Response.Headers.ContainsKey(AbpHttpConsts.AbpErrorFormat)) + { + // header 存在abp错误标头, 可以序列化错误信息 + error = await response.Content.ReadAsStringAsync(); + } + var errorContent = new StringContent(error) + { + Headers = { ContentType = new MediaTypeHeaderValue("application/json") } + }; + if (httpResponse.Response.Headers.ContainsKey(AbpHttpConsts.AbpErrorFormat)) + { + errorContent.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true"); + } + + return new DownstreamResponse( + errorContent, + (HttpStatusCode)errorItem.HttpStatusCode, + httpResponse.Response.Headers.Select(x => new Header(x.Key, x.Value)).ToList(), + errorItem.Message); + } + var route = httpResponse.Items.DownstreamRoute(); + var service = route.ServiceName ?? route.LoadBalancerKey ?? route.DownstreamPathTemplate.Value; + Logger.LogWarning($"The downstream service {service} returned an error, which is configured to be ignored"); + continue; + } + var content = await response.Content.ReadAsStringAsync(); var contentObject = JsonConvert.DeserializeObject(content); if (responseObject == null) { @@ -45,13 +94,16 @@ namespace Ocelot.Multiplexer Headers = { ContentType = new MediaTypeHeaderValue("application/json") } }; - if (responses.Any(response => response.Response.Headers.ContainsKey(AbpHttpConsts.AbpErrorFormat))) - { - stringContent.Headers.Add("_AbpErrorFormat", "true"); - } + //if (responses.Any(response => response.Response.Headers.ContainsKey(AbpHttpConsts.AbpErrorFormat))) + //{ + // stringContent.Headers.Add("_AbpErrorFormat", "true"); + //} - return new DownstreamResponse(stringContent, HttpStatusCode.OK, - new List>>(), "OK"); + return new DownstreamResponse( + stringContent, + HttpStatusCode.OK, + new List>>(), + "OK"); } } diff --git a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Program.cs b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Program.cs index f2e1169cb..612d86db5 100644 --- a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Program.cs +++ b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Program.cs @@ -1,57 +1,72 @@ -using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Serilog; using System; +using System.IO; +using System.Threading.Tasks; +using Volo.Abp.IO; +using Volo.Abp.Modularity.PlugIns; + +namespace LINGYUN.MicroService.Internal.ApiGateway; -namespace LINGYUN.MicroService.Internal.ApiGateway -{ - public class Program - { - public static int Main(string[] args) - { - try - { - var hostBuilder = CreateHostBuilder(args).Build(); - Log.Information("Starting ApiGateway.Host."); - hostBuilder.Run(); - - return 0; - } - catch (Exception ex) - { - Log.Fatal(ex, "Host terminated unexpectedly!"); - return 1; - } - finally - { - Log.CloseAndFlush(); - } - } - - internal static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }) - .ConfigureAppConfiguration((context, config) => - { - // 加入 ocelot配置文件 - config - .AddJsonFile($"ocelot.{context.HostingEnvironment.EnvironmentName ?? "Development"}.json", optional: true, reloadOnChange: true); - - var configuration = config.Build(); - if (configuration.GetSection("AgileConfig").Exists()) - { - config.AddAgileConfig(new AgileConfig.Client.ConfigClient(configuration)); - } - }) - .UseSerilog((context, provider, config) => - { - config.ReadFrom.Configuration(context.Configuration); - }) - .UseAutofac(); - } +public class Program +{ + public async static Task Main(string[] args) + { + try + { + Log.Information("Starting Internal ApiGateway."); + + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .ConfigureAppConfiguration((context, config) => + { + // 加入 ocelot配置文件 + config.AddJsonFile( + $"ocelot.{context.HostingEnvironment.EnvironmentName ?? "Development"}.json", + optional: true, + reloadOnChange: true); + + var configuration = config.Build(); + if (configuration.GetSection("AgileConfig").Exists()) + { + config.AddAgileConfig(new AgileConfig.Client.ConfigClient(configuration)); + } + }) + .UseSerilog((context, provider, config) => + { + config.ReadFrom.Configuration(context.Configuration); + }); + await builder.AddApplicationAsync(options => + { + // 搜索 Modules 目录下所有文件作为插件 + // 取消显示引用所有其他项目的模块,改为通过插件的形式引用 + var pluginFolder = Path.Combine( + Directory.GetCurrentDirectory(), "Modules"); + DirectoryHelper.CreateIfNotExists(pluginFolder); + options.PlugInSources.AddFolder( + pluginFolder, + SearchOption.AllDirectories); + }); + var app = builder.Build(); + await app.InitializeApplicationAsync(); + await app.RunAsync(); + return 0; + } + catch (Exception ex) + { + Log.Fatal(ex, "Host terminated unexpectedly!"); + Console.WriteLine("Host terminated unexpectedly!"); + Console.WriteLine(ex.ToString()); + return 1; + } + finally + { + Log.CloseAndFlush(); + } + } } diff --git a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Properties/launchSettings.json b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Properties/launchSettings.json index 6037e2ac6..20aace6df 100644 --- a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Properties/launchSettings.json +++ b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Properties/launchSettings.json @@ -12,7 +12,7 @@ "commandName": "Project", "launchBrowser": false, "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Production" }, "applicationUrl": "https://127.0.0.1:30443;http://127.0.0.1:30000" } diff --git a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Startup.cs b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Startup.cs deleted file mode 100644 index c34749dfe..000000000 --- a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Startup.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using System.IO; -using Volo.Abp.IO; -using Volo.Abp.Modularity.PlugIns; - -namespace LINGYUN.MicroService.Internal.ApiGateway -{ - public class Startup - { - public void ConfigureServices(IServiceCollection services) - { - services.AddApplication(options => - { - // 搜索 Modules 目录下所有文件作为插件 - // 取消显示引用所有其他项目的模块,改为通过插件的形式引用 - var pluginFolder = Path.Combine( - Directory.GetCurrentDirectory(), "Modules"); - DirectoryHelper.CreateIfNotExists(pluginFolder); - options.PlugInSources.AddFolder( - pluginFolder, - SearchOption.AllDirectories); - }); - } - - public void Configure(IApplicationBuilder app) - { - app.InitializeApplication(); - } - } -} diff --git a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.Development.json b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.Development.json index 473e8a26d..942a50e95 100644 --- a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.Development.json +++ b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.Development.json @@ -1370,6 +1370,56 @@ "UseTracing": true } }, + { + "DownstreamPathTemplate": "/api/abp/application-configuration", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "127.0.0.1", + "Port": 30040 + } + ], + "UpstreamPathTemplate": "/api/abp/task/application-configuration", + "UpstreamHttpMethod": [ "GET" ], + "LoadBalancerOptions": { + "Type": "RoundRobin" + }, + "RateLimitOptions": {}, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 10, + "DurationOfBreak": 1000, + "TimeoutValue": 10000 + }, + "HttpHandlerOptions": { + "UseTracing": true + }, + "Key": "task-configuration" + }, + { + "DownstreamPathTemplate": "/api/abp/api-definition", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "127.0.0.1", + "Port": 30040 + } + ], + "UpstreamPathTemplate": "/api/abp/task/api-definition", + "UpstreamHttpMethod": [ "GET" ], + "LoadBalancerOptions": { + "Type": "RoundRobin" + }, + "RateLimitOptions": {}, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 10, + "DurationOfBreak": 1000, + "TimeoutValue": 10000 + }, + "HttpHandlerOptions": { + "UseTracing": true + }, + "Key": "task-api-definition" + }, { "DownstreamPathTemplate": "/api/task-management/{everything}", "DownstreamScheme": "http", @@ -1585,7 +1635,8 @@ "backend-admin-api-definition", "messages-api-definition", "ids-admin-api-definition", - "localization-api-definition" + "localization-api-definition", + "task-api-definition" ], "UpstreamPathTemplate": "/api/abp/api-definition", "Aggregator": "AbpResponseMergeAggregator" @@ -1596,7 +1647,8 @@ "backend-admin-configuration", "messages-configuration", "ids-admin-configuration", - "localization-configuration" + "localization-configuration", + "task-configuration" ], "UpstreamPathTemplate": "/api/abp/application-configuration", "Aggregator": "AbpResponseMergeAggregator", diff --git a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.aggregate.json b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.aggregate.json index 28b82a9c1..3b6be4999 100644 --- a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.aggregate.json +++ b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.aggregate.json @@ -7,7 +7,8 @@ "backend-admin-api-definition", "messages-api-definition", "ids-admin-api-definition", - "localization-api-definition" + "localization-api-definition", + "task-api-definition" ], "UpstreamPathTemplate": "/api/abp/api-definition", "Aggregator": "AbpResponseMergeAggregator", @@ -20,7 +21,8 @@ "backend-admin-configuration", "messages-configuration", "ids-admin-configuration", - "localization-configuration" + "localization-configuration", + "task-configuration" ], "UpstreamPathTemplate": "/api/abp/application-configuration", "Aggregator": "AbpResponseMergeAggregator", diff --git a/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.task.json b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.task.json new file mode 100644 index 000000000..defae3d65 --- /dev/null +++ b/gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.task.json @@ -0,0 +1,87 @@ +{ + "Routes": [ + // ܶ˵ + { + "DownstreamPathTemplate": "/api/abp/application-configuration", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "127.0.0.1", + "Port": 30040 + } + ], + "UpstreamPathTemplate": "/api/abp/task/application-configuration", + "UpstreamHttpMethod": [ "GET" ], + "LoadBalancerOptions": { + "Type": "RoundRobin" + }, + "RateLimitOptions": {}, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 10, + "DurationOfBreak": 1000, + "TimeoutValue": 10000 + }, + "HttpHandlerOptions": { + "UseTracing": true + }, + "Key": "task-configuration" + }, + // ̬ܶAPI˵ + { + "DownstreamPathTemplate": "/api/abp/api-definition", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "127.0.0.1", + "Port": 30040 + } + ], + "UpstreamPathTemplate": "/api/abp/task/api-definition", + "UpstreamHttpMethod": [ "GET" ], + "LoadBalancerOptions": { + "Type": "RoundRobin" + }, + "RateLimitOptions": {}, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 10, + "DurationOfBreak": 1000, + "TimeoutValue": 10000 + }, + "HttpHandlerOptions": { + "UseTracing": true + }, + "Key": "task-api-definition" + }, + // + { + "DownstreamPathTemplate": "/api/task-management/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "127.0.0.1", + "Port": 30040 + } + ], + "UpstreamPathTemplate": "/api/task-management/{everything}", + "UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE" ], + "LoadBalancerOptions": { + "Type": "RoundRobin" + }, + "RateLimitOptions": { + "ClientWhitelist": [], + "EnableRateLimiting": true, + "Period": "1s", + "PeriodTimespan": 1, + "Limit": 5 + }, + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 10, + "DurationOfBreak": 1000, + "TimeoutValue": 10000 + }, + "HttpHandlerOptions": { + "UseTracing": true + } + } + ] +}