在微服务架构中,统一异常处理和日志记录更加复杂,因为服务之间需要独立且解耦,但仍需要统一的日志和异常处理策略,以便于监控、调试和运维。以下是基于 .NET 技术栈在微服务架构中实现这些功能的解决方案:
1. 统一异常处理
使用中间件 (Middleware)
每个微服务可以使用类似的中间件来处理全局异常:
public class ExceptionHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionHandlingMiddleware> _logger;
public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An unhandled exception has occurred.");
await HandleExceptionAsync(context, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var result = JsonConvert.SerializeObject(new { error = "An unexpected error occurred." });
return context.Response.WriteAsync(result);
}
}
在每个微服务的 Startup.cs
中配置该中间件:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// 其他中间件配置...
app.UseMiddleware<ExceptionHandlingMiddleware>();
// 其他中间件配置...
}
2. 统一日志记录
使用集中化的日志管理工具
在微服务架构中,推荐使用集中化日志管理工具,例如 ELK(Elasticsearch, Logstash, Kibana)或 Prometheus + Grafana。
使用 Serilog 和 ElasticSearch
- 安装 Serilog 和 ElasticSearch sink:
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.Elasticsearch
- 配置 Serilog:
在 Program.cs
中进行配置:
public class Program
{
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200"))
{
AutoRegisterTemplate = true,
IndexFormat = "logstash-{0:yyyy.MM.dd}"
})
.CreateLogger();
try
{
Log.Information("Starting web host");
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog() // 使用 Serilog
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
3. 业务流转日志处理
为了在微服务架构中处理业务流转日志,可以采用事件驱动架构和分布式追踪。
使用事件驱动架构
通过事件总线(如 RabbitMQ, Kafka)来发布和订阅业务事件:
- 发布事件:
public class OrderService
{
private readonly IEventBus _eventBus;
public OrderService(IEventBus eventBus)
{
_eventBus = eventBus;
}
public void ProcessOrder(Order order)
{
// 处理订单逻辑
_eventBus.Publish(new OrderProcessedEvent(order));
}
}
- 订阅事件:
public class OrderProcessedEventHandler : IEventHandler<OrderProcessedEvent>
{
private readonly ILogger<OrderProcessedEventHandler> _logger;
public OrderProcessedEventHandler(ILogger<OrderProcessedEventHandler> logger)
{
_logger = logger;
}
public Task Handle(OrderProcessedEvent @event)
{
_logger.LogInformation("Order processed: {OrderId}", @event.Order.Id);
return Task.CompletedTask;
}
}
4. 分布式追踪
使用分布式追踪工具,如 Jaeger 或 Zipkin,来追踪跨服务的请求流:
集成 Jaeger
- 安装包:
dotnet add package OpenTelemetry.Exporter.Jaeger
dotnet add package OpenTelemetry.Extensions.Hosting
- 配置 OpenTelemetry:
在 Startup.cs
中进行配置:
public void ConfigureServices(IServiceCollection services)
{
services.AddOpenTelemetryTracing(builder =>
{
builder.AddAspNetCoreInstrumentation()
.AddJaegerExporter(o =>
{
o.AgentHost = "localhost";
o.AgentPort = 6831;
});
});
// 其他服务配置...
}
5. 综合配置
确保在每个微服务中配置日志、异常处理、事件总线和分布式追踪,并通过统一的监控平台(如 ELK 或 Prometheus + Grafana)来集中管理日志和监控数据。
总结
通过以上方法,可以在基于 .NET 技术栈的微服务架构中实现统一异常处理和日志记录。使用中间件实现全局异常处理,使用 Serilog 和 ElasticSearch 实现集中化日志管理,通过事件驱动架构处理业务流转日志,并使用分布式追踪工具实现跨服务的请求追踪。这些方法有助于提升系统的可靠性、可维护性和可监控性。