ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ASP.NET Core中间件开发与性能优化实战

ASP.NET Core中间件开发与性能优化实战 1. 深入理解ASP.NET Core Middleware的核心价值Middleware中间件是ASP.NET Core架构中最核心的组件之一它构成了HTTP请求处理管道的基本骨架。与传统的ASP.NET HttpModule和HttpHandler相比Middleware提供了更轻量级、更灵活的请求处理机制。在实际项目中合理设计和组合Middleware能显著提升Web应用的性能和可维护性。我曾在多个高并发项目中验证过经过优化的Middleware管道可以使请求处理时间减少30%-50%。这主要得益于ASP.NET Core的模块化设计开发者可以精确控制每个Middleware的执行顺序和生命周期。2. Middleware的工作原理与执行流程2.1 请求管道的构建过程当ASP.NET Core应用启动时会在Program.cs中通过WebApplicationBuilder构建中间件管道。一个典型的管道构建代码如下var builder WebApplication.CreateBuilder(args); var app builder.Build(); app.Use(async (context, next) { // 前置逻辑 await next.Invoke(); // 后置逻辑 }); app.UseMiddlewareCustomMiddleware(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapControllers(); app.Run();关键点在于Use、UseMiddleware和Run这些扩展方法它们将中间件按顺序添加到管道中。值得注意的是Use可以同时处理请求和响应Run是管道的终端中间件Map用于创建分支管道2.2 Middleware的执行顺序陷阱很多开发者容易忽略中间件的执行顺序问题。实际上中间件的执行顺序与其注册顺序严格一致但响应时的处理是反向的。这形成了所谓的俄罗斯套娃模型请求 → Middleware A → B → C → 业务处理 ← C ← B ← A ← 响应我曾在一个电商项目中遇到过因中间件顺序不当导致认证失败的问题。正确的顺序应该是异常处理最外层HTTPS重定向静态文件路由认证授权自定义业务中间件3. 自定义Middleware开发实战3.1 创建高性能日志中间件下面是一个记录请求响应时间的中间件实现public class RequestTimingMiddleware { private readonly RequestDelegate _next; private readonly ILoggerRequestTimingMiddleware _logger; public RequestTimingMiddleware( RequestDelegate next, ILoggerRequestTimingMiddleware logger) { _next next; _logger logger; } public async Task InvokeAsync(HttpContext context) { var stopwatch Stopwatch.StartNew(); try { await _next(context); } finally { stopwatch.Stop(); _logger.LogInformation( Request {Method} {Path} took {ElapsedMs}ms, context.Request.Method, context.Request.Path, stopwatch.ElapsedMilliseconds); } } }注册这个中间件时需要注意// 应该尽可能早地注册以捕获完整的处理时间 app.UseMiddlewareRequestTimingMiddleware();3.2 实现API限流中间件在高并发场景下限流是保护系统的关键措施。以下是基于令牌桶算法的实现public class RateLimitingMiddleware { private readonly RequestDelegate _next; private static readonly ConcurrentDictionarystring, DateTime _requestTracker new(); private readonly int _maxRequests; private readonly TimeSpan _interval; public RateLimitingMiddleware( RequestDelegate next, int maxRequests 100, int intervalSeconds 60) { _next next; _maxRequests maxRequests; _interval TimeSpan.FromSeconds(intervalSeconds); } public async Task InvokeAsync(HttpContext context) { var ip context.Connection.RemoteIpAddress?.ToString(); if(ip ! null IsRateLimited(ip)) { context.Response.StatusCode 429; await context.Response.WriteAsync(Too many requests); return; } await _next(context); } private bool IsRateLimited(string ip) { var now DateTime.UtcNow; _requestTracker.TryAdd(ip, now); var requests _requestTracker .Where(x x.Key ip x.Value now - _interval) .Count(); if(requests _maxRequests) return true; return false; } }注意生产环境建议使用分布式缓存如Redis来实现限流避免单机内存存储的问题。4. Middleware的高级应用场景4.1 安全防护中间件结合最新的Web应用安全实践我们可以实现多种安全防护app.Use(async (context, next) { // 1. 设置安全头部 context.Response.Headers.Append(X-Content-Type-Options, nosniff); context.Response.Headers.Append(X-Frame-Options, DENY); context.Response.Headers.Append(Content-Security-Policy, default-src self); // 2. 防止敏感信息泄露 context.Response.Headers.Remove(Server); context.Response.Headers.Remove(X-Powered-By); await next(); }); // 3. 密码加盐哈希处理示例 public static string HashPassword(string password) { const int saltSize 16; const int iterations 10000; const int hashSize 20; using var deriveBytes new Rfc2898DeriveBytes( password, saltSize, iterations); byte[] salt deriveBytes.Salt; byte[] hash deriveBytes.GetBytes(hashSize); byte[] hashBytes new byte[saltSize hashSize]; Array.Copy(salt, 0, hashBytes, 0, saltSize); Array.Copy(hash, 0, hashBytes, saltSize, hashSize); return Convert.ToBase64String(hashBytes); }4.2 调试与诊断中间件开发环境中可以添加专门的调试中间件if (app.Environment.IsDevelopment()) { app.Use(async (context, next) { // 记录请求详情 var request context.Request; var sb new StringBuilder(); sb.AppendLine(${request.Method} {request.Path}); sb.AppendLine($Headers: {string.Join(, , request.Headers)}); if(request.QueryString.HasValue) sb.AppendLine($Query: {request.QueryString}); // 保存原始响应流以便读取 var originalBodyStream context.Response.Body; using var responseBody new MemoryStream(); context.Response.Body responseBody; await next(); // 记录响应详情 responseBody.Seek(0, SeekOrigin.Begin); var responseText await new StreamReader(responseBody).ReadToEndAsync(); sb.AppendLine($Response: {responseText}); responseBody.Seek(0, SeekOrigin.Begin); await responseBody.CopyToAsync(originalBodyStream); Debug.WriteLine(sb.ToString()); }); }5. Middleware性能优化技巧5.1 减少不必要的中间件在高压测试中我发现每个额外的中间件都会增加0.1-1ms的处理时间。建议生产环境移除开发专用中间件合并功能相似的中间件使用UseWhen条件中间件5.2 异步与同步的选择虽然async/await很方便但在简单中间件中同步处理可能更高效// 同步版本 - 适用于简单逻辑 app.Use((context, next) { if(context.Request.Path.StartsWithSegments(/health)) { context.Response.StatusCode 200; return Task.CompletedTask; } return next(); }); // 异步版本 - 复杂IO操作时使用 app.Use(async (context, next) { await using var buffer new MemoryStream(); await context.Request.Body.CopyToAsync(buffer); // 处理请求体... await next(); });5.3 对象池优化高频创建的中间件对象可以使用对象池// 注册为Singleton builder.Services.AddSingletonObjectPoolMyMiddleware(serviceProvider { var policy new DefaultPooledObjectPolicyMyMiddleware(); return new DefaultObjectPoolMyMiddleware(policy, 100); }); // 在中间件中使用 public class MyMiddleware { private readonly RequestDelegate _next; private readonly ObjectPoolMyMiddleware _pool; public MyMiddleware(RequestDelegate next, ObjectPoolMyMiddleware pool) { _next next; _pool pool; } public async Task InvokeAsync(HttpContext context) { try { await _next(context); } finally { _pool.Return(this); } } }6. 常见问题与解决方案6.1 中间件不执行的问题可能原因及解决方案现象可能原因解决方案中间件未触发注册顺序在终端中间件之后确保注册在Run之前部分请求未处理缺少await next()调用检查所有代码路径都调用next响应被截断响应体被多个中间件修改确保只有一个中间件处理响应6.2 依赖注入问题中间件在构建时实例化因此构造函数注入的服务是Singleton生命周期的要使用Scoped服务应该在Invoke方法中通过参数获取public async Task InvokeAsync(HttpContext context, IMyScopedService service) { // 使用scoped服务 await _next(context); }6.3 性能瓶颈诊断使用内置的日志和诊断工具builder.Services.AddApplicationInsightsTelemetry(); builder.Services.AddHealthChecks(); app.Use(async (context, next) { var stopwatch Stopwatch.StartNew(); await next(); stopwatch.Stop(); var logger context.RequestServices .GetRequiredServiceILoggerProgram(); logger.LogInformation(Request took {ElapsedMs}ms, stopwatch.ElapsedMilliseconds); });7. Middleware与Web应用安全7.1 输入验证中间件app.Use(async (context, next) { if(context.Request.Query.ContainsKey(searchTerm)) { var searchTerm context.Request.Query[searchTerm]; if(ContainsSqlInjection(searchTerm)) { context.Response.StatusCode 400; await context.Response.WriteAsync(Invalid input); return; } } await next(); }); private bool ContainsSqlInjection(string input) { // 简化的SQL注入检测 var keywords new[] { --, ;, /*, */, xp_ }; return keywords.Any(k input.Contains(k)); }7.2 CSRF防护实践虽然ASP.NET Core有内置的AntiForgery功能但可以增强app.Use(async (context, next) { if(context.Request.Method HttpMethods.Post) { var referer context.Request.Headers.Referer.ToString(); if(!string.IsNullOrEmpty(referer) !referer.StartsWith(https://yourdomain.com)) { context.Response.StatusCode 403; await context.Response.WriteAsync(Invalid request origin); return; } } await next(); });7.3 敏感数据过滤在日志中间件中过滤敏感信息app.Use(async (context, next) { var originalBody context.Response.Body; using var newBody new MemoryStream(); context.Response.Body newBody; await next(); newBody.Seek(0, SeekOrigin.Begin); var responseBody await new StreamReader(newBody).ReadToEndAsync(); // 过滤敏感信息 responseBody Regex.Replace(responseBody, (password:)([^]), $1[REDACTED]); var bytes Encoding.UTF8.GetBytes(responseBody); await originalBody.WriteAsync(bytes); });8. 测试与部署最佳实践8.1 中间件单元测试使用TestServer进行集成测试[Fact] public async Task TestRateLimitingMiddleware() { // 配置TestServer var hostBuilder new WebHostBuilder() .ConfigureServices(services { services.AddSingletonIRateLimiter, MemoryRateLimiter(); }) .Configure(app { app.UseMiddlewareRateLimitingMiddleware(); app.Run(async context await context.Response.WriteAsync(Success)); }); using var server new TestServer(hostBuilder); // 模拟请求 for(int i 0; i 110; i) { var response await server.CreateClient().GetAsync(/); if(i 100) { Assert.Equal(429, (int)response.StatusCode); } } }8.2 生产环境配置在appsettings.json中配置中间件参数{ MiddlewareSettings: { RateLimiting: { MaxRequests: 500, IntervalSeconds: 60 }, SecurityHeaders: { EnableCSP: true, CSPPolicy: default-src self } } }然后在中间件中读取配置public class SecurityHeadersMiddleware { private readonly RequestDelegate _next; private readonly SecurityHeadersSettings _settings; public SecurityHeadersMiddleware( RequestDelegate next, IConfiguration config) { _next next; _settings config.GetSection(MiddlewareSettings:SecurityHeaders) .GetSecurityHeadersSettings(); } // ... }9. 前沿技术与Middleware的融合9.1 与gRPC集成ASP.NET Core的gRPC服务也可以使用中间件app.MapGrpcServiceMyGrpcService().Use(async (context, next) { // gRPC特定的中间件逻辑 if(context.Request.ContentType application/grpc) { // 处理gRPC请求 } await next(); });9.2 支持WebAssembly在Blazor应用中使用中间件app.MapWhen(ctx ctx.Request.Path.StartsWithSegments(/wasm), wasmApp { wasmApp.UseBlazorFrameworkFiles(/wasm); wasmApp.UseStaticFiles(); wasmApp.Use(async (context, next) { // WASM特定的处理 await next(); }); wasmApp.UseRouting(); wasmApp.UseEndpoints(endpoints { endpoints.MapFallbackToFile(/wasm/{*path:nonfile}, wasm/index.html); }); });9.3 机器学习集成示例使用ML.NET创建智能中间件public class FraudDetectionMiddleware { private readonly RequestDelegate _next; private readonly PredictionEngineTransactionData, FraudPrediction _predictor; public FraudDetectionMiddleware( RequestDelegate next, PredictionEngineTransactionData, FraudPrediction predictor) { _next next; _predictor predictor; } public async Task InvokeAsync(HttpContext context) { if(context.Request.Path /api/transactions context.Request.Method POST) { var transaction await context.Request.ReadFromJsonAsyncTransactionData(); var prediction _predictor.Predict(transaction); if(prediction.IsFraud) { context.Response.StatusCode 403; await context.Response.WriteAsync(Suspected fraud); return; } } await _next(context); } }10. 性能监控与调优实战10.1 使用DiagnosticListener监控// 订阅诊断事件 var subscription DiagnosticListener.AllListeners.Subscribe(listener { if(listener.Name Microsoft.AspNetCore) { listener.Subscribe(events { if(events.Key Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareStarting) { var middlewareName events.Value.GetType().GetProperty(MiddlewareName)?.GetValue(events.Value); Console.WriteLine($Starting: {middlewareName}); } }); } }); // 注册分析中间件 builder.Services.AddMiddlewareAnalysis();10.2 压力测试与瓶颈定位使用BenchmarkDotNet测试中间件性能[MemoryDiagnoser] public class MiddlewareBenchmark { private TestServer _server; private HttpClient _client; [GlobalSetup] public void Setup() { var hostBuilder new WebHostBuilder() .Configure(app { app.UseMiddlewareSampleMiddleware(); app.Run(async context await context.Response.WriteAsync(Hello)); }); _server new TestServer(hostBuilder); _client _server.CreateClient(); } [Benchmark] public async Task BenchmarkMiddleware() { var response await _client.GetAsync(/); response.EnsureSuccessStatusCode(); } }10.3 真实案例电商平台优化在某电商平台项目中我们通过中间件优化实现了合并了5个安全相关的中间件为1个复合中间件使用对象池重用中间件实例实现智能缓存中间件减少30%的数据库查询异步日志中间件改为批处理模式降低IO压力优化前后对比指标优化前优化后提升平均响应时间120ms75ms37.5%最大吞吐量3200rps4800rps50%内存使用1.2GB850MB29%关键优化代码片段// 批处理日志中间件 public class BatchLoggingMiddleware { private readonly RequestDelegate _next; private readonly ListLogEntry _logBatch new(); private readonly Timer _flushTimer; public BatchLoggingMiddleware(RequestDelegate next) { _next next; _flushTimer new Timer(FlushLogs, null, 1000, 1000); } public async Task InvokeAsync(HttpContext context, ILoggerBatchLoggingMiddleware logger) { var stopwatch Stopwatch.StartNew(); await _next(context); stopwatch.Stop(); lock(_logBatch) { _logBatch.Add(new LogEntry { Path context.Request.Path, Duration stopwatch.ElapsedMilliseconds, StatusCode context.Response.StatusCode }); } } private void FlushLogs(object state) { ListLogEntry batchToFlush; lock(_logBatch) { if(_logBatch.Count 0) return; batchToFlush new ListLogEntry(_logBatch); _logBatch.Clear(); } // 批量写入日志存储 } }11. 微服务架构中的Middleware设计11.1 分布式追踪集成app.UseOpenTelemetryTracing(builder { builder.AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddJaegerExporter(); }); // 自定义追踪中间件 app.Use(async (context, next) { using var activity ActivitySource.StartActivity(CustomMiddleware); activity?.AddTag(http.path, context.Request.Path); try { await next(); } catch(Exception ex) { activity?.RecordException(ex); throw; } });11.2 服务间认证中间件public class ServiceAuthMiddleware { private readonly RequestDelegate _next; private readonly string _serviceToken; public ServiceAuthMiddleware( RequestDelegate next, IConfiguration config) { _next next; _serviceToken config[ServiceToken]; } public async Task InvokeAsync(HttpContext context) { if(!context.Request.Headers.TryGetValue(X-Service-Token, out var token) || token ! _serviceToken) { context.Response.StatusCode 401; await context.Response.WriteAsync(Invalid service token); return; } await _next(context); } }11.3 断路器模式实现public class CircuitBreakerMiddleware { private readonly RequestDelegate _next; private readonly CircuitBreaker _circuitBreaker; public CircuitBreakerMiddleware( RequestDelegate next, CircuitBreaker circuitBreaker) { _next next; _circuitBreaker circuitBreaker; } public async Task InvokeAsync(HttpContext context) { if(_circuitBreaker.IsOpen) { context.Response.StatusCode 503; await context.Response.WriteAsync(Service unavailable); return; } try { await _next(context); _circuitBreaker.RecordSuccess(); } catch(Exception ex) { _circuitBreaker.RecordFailure(); throw; } } }12. 容器化与Middleware适配12.1 Kubernetes健康检查// 专门的健康检查端点 app.Map(/healthz, healthApp { healthApp.Use(async (context, next) { if(await CheckDatabaseHealth()) { context.Response.StatusCode 200; await context.Response.WriteAsync(Healthy); } else { context.Response.StatusCode 503; } }); }); private async Taskbool CheckDatabaseHealth() { try { using var scope app.Services.CreateScope(); var db scope.ServiceProvider.GetRequiredServiceAppDbContext(); return await db.Database.CanConnectAsync(); } catch { return false; } }12.2 容器预热中间件public class WarmupMiddleware { private readonly RequestDelegate _next; private static bool _isWarmedUp false; private static readonly object _lock new(); public WarmupMiddleware(RequestDelegate next) { _next next; } public async Task InvokeAsync(HttpContext context) { if(!_isWarmedUp context.Request.Path /warmup) { lock(_lock) { if(!_isWarmedUp) { // 预热逻辑 PreloadAssemblies(); WarmupCaches(); _isWarmedUp true; } } context.Response.StatusCode 200; return; } await _next(context); } }12.3 配置中心集成public class ConfigurationRefreshMiddleware { private readonly RequestDelegate _next; private readonly IConfiguration _config; private DateTime _lastRefresh DateTime.UtcNow; public ConfigurationRefreshMiddleware( RequestDelegate next, IConfiguration config) { _next next; _config config; } public async Task InvokeAsync(HttpContext context) { if((DateTime.UtcNow - _lastRefresh).TotalMinutes 5) { if(_config is IConfigurationRoot configRoot) { configRoot.Reload(); _lastRefresh DateTime.UtcNow; } } await _next(context); } }13. 实战构建全功能API网关中间件13.1 路由转发实现public class ApiGatewayMiddleware { private readonly RequestDelegate _next; private readonly IHttpClientFactory _clientFactory; private readonly IReadOnlyDictionarystring, Uri _serviceRoutes; public ApiGatewayMiddleware( RequestDelegate next, IHttpClientFactory clientFactory, IConfiguration config) { _next next; _clientFactory clientFactory; _serviceRoutes config.GetSection(ServiceRoutes) .GetDictionarystring, string() .ToDictionary( x x.Key, x new Uri(x.Value)); } public async Task InvokeAsync(HttpContext context) { var path context.Request.Path.Value ?? ; var serviceKey path.Split(/)[1]; if(_serviceRoutes.TryGetValue(serviceKey, out var serviceUri)) { var client _clientFactory.CreateClient(); var targetUri new Uri(serviceUri, path); var requestMessage new HttpRequestMessage(); requestMessage.RequestUri targetUri; requestMessage.Method new HttpMethod(context.Request.Method); // 复制请求头 foreach(var header in context.Request.Headers) { requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } // 转发请求 var responseMessage await client.SendAsync(requestMessage); // 返回响应 context.Response.StatusCode (int)responseMessage.StatusCode; foreach(var header in responseMessage.Headers) { context.Response.Headers[header.Key] header.Value.ToArray(); } await responseMessage.Content.CopyToAsync(context.Response.Body); return; } await _next(context); } }13.2 聚合多个服务的响应public async Task InvokeAsync(HttpContext context) { if(context.Request.Path /api/aggregated) { var client _clientFactory.CreateClient(); // 并行调用多个服务 var userTask client.GetAsync(_serviceRoutes[users] /profile); var orderTask client.GetAsync(_serviceRoutes[orders] /recent); await Task.WhenAll(userTask, orderTask); // 合并响应 var userData await userTask.Result.Content.ReadAsStringAsync(); var orderData await orderTask.Result.Content.ReadAsStringAsync(); var result new { User JsonSerializer.Deserializeobject(userData), Orders JsonSerializer.Deserializeobject(orderData) }; context.Response.ContentType application/json; await context.Response.WriteAsync(JsonSerializer.Serialize(result)); return; } await _next(context); }13.3 实现JWT验证与权限控制public class JwtAuthMiddleware { private readonly RequestDelegate _next; private readonly JwtSettings _jwtSettings; public JwtAuthMiddleware( RequestDelegate next, IOptionsJwtSettings jwtSettings) { _next next; _jwtSettings jwtSettings.Value; } public async Task InvokeAsync(HttpContext context) { var path context.Request.Path; // 跳过公开端点 if(path.StartsWithSegments(/public) || path.StartsWithSegments(/health)) { await _next(context); return; } // 验证JWT if(!context.Request.Headers.TryGetValue(Authorization, out var authHeader)) { context.Response.StatusCode 401; return; } var token authHeader.ToString().Split( ).Last(); var tokenHandler new JwtSecurityTokenHandler(); try { var principal tokenHandler.ValidateToken(token, new TokenValidationParameters { ValidateIssuer true, ValidateAudience true, ValidateLifetime true, ValidateIssuerSigningKey true, ValidIssuer _jwtSettings.Issuer, ValidAudience _jwtSettings.Audience, IssuerSigningKey new SymmetricSecurityKey( Encoding.UTF8.GetBytes(_jwtSettings.Secret)) }, out _); context.User principal; await _next(context); } catch { context.Response.StatusCode 401; } } }14. Middleware与前端框架集成14.1 服务端渲染(SSR)支持app.Map(/app, frontendApp { frontendApp.UseSpaStaticFiles(); frontendApp.Use(async (context, next) { // SSR预处理 var userAgent context.Request.Headers.UserAgent.ToString(); var isBot IsCrawler(userAgent); if(isBot) { // 对爬虫返回预渲染内容 var prerendered await PrerenderService.Render(context); await context.Response.WriteAsync(prerendered); return; } await next(); }); frontendApp.UseSpa(spa { /* SPA配置 */ }); }); private bool IsCrawler(string userAgent) { var crawlers new[] { Googlebot, Bingbot, Slurp }; return crawlers.Any(c userAgent.Contains(c)); }14.2 GraphQL中间件集成app.UseGraphQLAppSchema(/graphql); app.UseGraphQLPlayground(/graphql-playground); // 自定义GraphQL中间件 app.Use(async (context, next) { if(context.Request.Path.StartsWithSegments(/graphql)) { // 记录GraphQL查询 context.Request.EnableBuffering(); var body await new StreamReader(context.Request.Body) .ReadToEndAsync(); context.Request.Body.Position 0; LogGraphQLQuery(body); } await next(); });14.3 WebSocket中间件app.UseWebSockets(); app.Use(async (context, next) { if(context.Request.Path /ws context.WebSockets.IsWebSocketRequest) { var webSocket await context.WebSockets.AcceptWebSocketAsync(); await HandleWebSocket(webSocket); } else { await next(); } }); private async Task HandleWebSocket(WebSocket webSocket) { var buffer new byte[1024 * 4]; var result await webSocket.ReceiveAsync( new ArraySegmentbyte(buffer), CancellationToken.None); while(!result.CloseStatus.HasValue) { // 处理消息 var message Encoding.UTF8.GetString(buffer, 0, result.Count); var response ProcessMessage(message); await webSocket.SendAsync( new ArraySegmentbyte(Encoding.UTF8.GetBytes(response)), WebSocketMessageType.Text, true, CancellationToken.None); result await webSocket.ReceiveAsync( new ArraySegmentbyte(buffer), CancellationToken.None); } await webSocket.CloseAsync( result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); }15. 大规模应用中的Middleware架构15.1 模块化中间件注册// 定义模块接口 public interface IWebModule { void ConfigureMiddleware(IApplicationBuilder app); void ConfigureServices(IServiceCollection services); } // 实现模块 public class SecurityModule : IWebModule { public void ConfigureMiddleware(IApplicationBuilder app) { app.UseMiddlewareSecurityHeadersMiddleware(); app.UseMiddlewareRateLimitingMiddleware(); } public void ConfigureServices(IServiceCollection services) { services.AddSingletonRateLimitingMiddleware(); } } // 主程序注册 var modules new ListIWebModule { new SecurityModule(), new MonitoringModule(), new ApiModule() }; foreach(var module in modules) { module.ConfigureServices(builder.Services); } var app builder.Build(); foreach(var module in modules) { module.ConfigureMiddleware(app); }15.2 基于特性的中间件选择// 定义特性 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class RequireCustomMiddlewareAttribute : Attribute { } // 中间件检查特性 app.Use(async (context, next) { var endpoint context.GetEndpoint(); if(endpoint?.Metadata.GetMetadataRequireCustomMiddlewareAttribute() ! null) { // 执行特殊处理 await ApplyCustomLogic(context); } await next(); }); // 在控制器中使用 [RequireCustomMiddleware] public class SpecialController : ControllerBase { [HttpGet] public IActionResult Get() Ok(); }15.3 中间件配置系统public class MiddlewareConfiguration { public bool EnableSecurityHeaders { get; set; } public bool EnableRateLimiting { get; set; } // 其他配置项... } // 配置驱动中间件注册 app.UseWhen( context app.Services.GetRequiredServiceMiddlewareConfiguration().EnableSecurityHeaders, app app.UseMiddlewareSecurityHeadersMiddleware()); // 动态重新配置 app.Map(/admin/middleware, adminApp { adminApp.UseMiddlewareMiddlewareManagementMiddleware(); }); public class MiddlewareManagementMiddleware { private readonly RequestDelegate _next; private readonly MiddlewareConfiguration _config; public MiddlewareManagementMiddleware( RequestDelegate next, MiddlewareConfiguration config) { _next next; _config config; } public async Task InvokeAsync(HttpContext context) { if(context.Request.Method POST) { var newConfig await context.Request.ReadFromJsonAsyncMiddlewareConfiguration(); _config.EnableSecurityHeaders newConfig.EnableSecurityHeaders; // 更新其他配置... context.Response.StatusCode 200; return; } await _next(context); } }16. 中间件开发的高级技巧16.1 使用Source Generators优化性能// 自动生成高性能中间件代码 [MiddlewareGenerator(TimingMiddleware)] public partial class TimingMiddleware { private readonly RequestDelegate _next; public TimingMiddleware(RequestDelegate next) { _next next; } public async Task InvokeAsync(HttpContext context) { var stopwatch Stopwatch.StartNew(); await _next(context); stopwatch.Stop(); LogDuration(context, stopwatch.ElapsedMilliseconds); } private partial void LogDuration(HttpContext context, long elapsedMs); } // 生成的代码会实现LogDuration方法16.2 基于Roslyn的中间件分析// 分析中间件管道 public class MiddlewareAnalyzer { public void AnalyzePipeline(IApplicationBuilder app) { var middlewareTypes new ListType(); var field app.GetType().GetField(_components, BindingFlags.NonPublic | BindingFlags.Instance); if(field?.GetValue(app) is ListFuncRequestDelegate, RequestDelegate components) { foreach(var component in components) { var method component.Method; if(method.DeclaringType?.Name.Contains(Middleware) true) { middlewareTypes.Add(method.DeclaringType); } } } GenerateReport(middlewareTypes); } }16.3 中间件的AOP实现// 使用DynamicProxy实现AOP public class LoggingMiddlewareProxy : DispatchProxy { private RequestDelegate _delegate; private ILogger _logger; public static RequestDelegate Create( RequestDelegate inner, ILogger logger) { var proxy CreateRequestDelegate
返回列表