Browse Source

feat: 增加对聚合错误处理

pull/467/head
cKey 4 years ago
parent
commit
6b0c5ec827
  1. 2
      aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Program.cs
  2. 2
      aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Program.cs
  3. 2
      aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Program.cs
  4. 2
      aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Program.cs
  5. 8
      aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Program.cs
  6. 2
      aspnet-core/services/LY.MicroService.identityServer.HttpApi.Host/Program.cs
  7. 2
      aspnet-core/services/LY.MicroService.identityServer/Program.cs
  8. 5
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/InternalApiGatewayOptions.cs
  9. 68
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Ocelot/Multiplexer/AbpResponseMergeAggregator.cs
  10. 115
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Program.cs
  11. 2
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Properties/launchSettings.json
  12. 31
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Startup.cs
  13. 56
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.Development.json
  14. 6
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.aggregate.json
  15. 87
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/ocelot.task.json

2
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

2
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

2
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

2
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

8
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();

2
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

2
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

5
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
{
/// <summary>
/// 聚合异常时是否忽略
/// </summary>
public bool AggregationIgnoreError { get; set; }
public DownstreamOpenApi[] DownstreamOpenApis { get; set; }
public InternalApiGatewayOptions()
{
AggregationIgnoreError = true;
DownstreamOpenApis = new DownstreamOpenApi[0];
}
}

68
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<AbpResponseMergeAggregator> Logger { protected get; set; }
protected InternalApiGatewayOptions Options { get; }
public AbpResponseMergeAggregator(
IOptions<InternalApiGatewayOptions> options)
{
Options = options.Value;
Logger = NullLogger<AbpResponseMergeAggregator>.Instance;
}
public async Task<DownstreamResponse> Aggregate(List<HttpContext> 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<KeyValuePair<string, IEnumerable<string>>>(), "OK");
return new DownstreamResponse(
stringContent,
HttpStatusCode.OK,
new List<KeyValuePair<string, IEnumerable<string>>>(),
"OK");
}
}

115
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<Startup>();
})
.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<int> 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<InternalApiGatewayModule>(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();
}
}
}

2
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"
}

31
gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.Internal.ApiGateway/Startup.cs

@ -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<InternalApiGatewayModule>(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();
}
}
}

56
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",

6
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",

87
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
}
}
]
}
Loading…
Cancel
Save