You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core页面加载时间中间件致应用挂起问题排查求助

问题原因与调试方案

核心原因

你的中间件出现挂起的本质问题是响应头写入时机错误:
当await _next(context)执行完成后,MVC已经完成了响应内容的输出,响应头已经发送到客户端。此时ASP.NET Core会阻止修改响应头(HTTP协议要求响应头必须在响应体之前发送),强行写入会触发内部线程阻塞,最终导致应用挂起。

另外如果中间件注册顺序错误(比如放在app.MapControllers等终端中间件之后),会加重这个问题——终端中间件直接完成响应,后续的响应头写入操作会直接触发阻塞。

调试与排查方法

  • 检查响应状态:在添加响应头前先判断context.Response.HasStarted,确认是否还能写入响应头:
    if (!context.Response.HasStarted)
    {
        context.Response.Headers.Add("X-PageLoadTime", elapsedMilliseconds.ToString());
    }
    
  • 调整中间件注册顺序:把app.UseMiddleware<PageLoadTimeMiddleware>()放在所有终端中间件(如app.MapControllers、app.MapRazorPages)之前,确保在响应开始生成前完成中间件的前置逻辑。
  • 添加日志追踪:给中间件注入ILogger,在关键节点输出日志,跟踪响应状态和耗时数据:
    // 构造函数注入ILogger<PageLoadTimeMiddleware>
    _logger.LogInformation("Tracking load time for request: {Path}", context.Request.Path);
    await _next(context);
    _logger.LogInformation("Response started status: {Status}", context.Response.HasStarted);
    _logger.LogInformation("Request elapsed time: {Ms}ms", stopwatch.ElapsedMilliseconds);
    
  • 断点调试:在Visual Studio中给await _next(context)前后设置断点,查看context.Response.HasStarted的变化,确认响应是否在中间件执行后续逻辑前已经发送。

修正后的中间件代码

public sealed class PageLoadTimeMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<PageLoadTimeMiddleware> _logger;

    public PageLoadTimeMiddleware(RequestDelegate next, ILogger<PageLoadTimeMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context)
    {
        var stopwatch = Stopwatch.StartNew();

        try
        {
            await _next(context);
        }
        finally
        {
            stopwatch.Stop();
            var elapsedMilliseconds = stopwatch.ElapsedMilliseconds;

            // 仅在响应未开始时添加头
            if (!context.Response.HasStarted)
            {
                context.Response.Headers.TryAdd("X-PageLoadTime", elapsedMilliseconds.ToString());
            }
            else
            {
                _logger.LogWarning("Failed to add X-PageLoadTime header: response already sent for {Path}", context.Request.Path);
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Goober

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:12:41