在所有中间件执行完成之前,http响应数据包是否开始发送给调用方? (aspnetcore)

时间:2019-12-03 23:12:46

标签: c# asp.net-core .net-core

我们具有以下设置-> Azure API管理层调用容器中Service Fabric上托管的Web api。 Web API使用MVC在ASP Netcore上运行。我们的代码中有很多中间件,我们在每个中间件中测量请求的延迟。我们还将在调用方(Azure API管理层)上测量请求的延迟。

我们看到的是,对于某些调用,在上一个中间件中测量的延迟为10秒,而在倒数第二个中间件和更高的Azure API管理层中,相同的延迟量度为200ms。那是巨大的差异。提供的原因是,API管理层在获得第一个数据包后就开始测量请求的结束时间延迟。

Http请求是否有可能甚至在所有中间件执行完毕之前就开始向呼叫者发送数据包?

2 个答案:

答案 0 :(得分:1)

是的,中间件有可能开始编写响应。

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {

            await context.Response.WriteAsync(
                $"Hello {CultureInfo.CurrentCulture.DisplayName}");
            // Call the next delegate/middleware in the pipeline
            await next();
        });

        app.Run(async (context) =>
        {
            //this is just starting, yet the response already started
            //and the current culture info change is not used in the response.
            var cultureQuery = context.Request.Query["culture"];
            if (!string.IsNullOrWhiteSpace(cultureQuery))
            {
                var culture = new CultureInfo(cultureQuery);

                CultureInfo.CurrentCulture = culture;
                CultureInfo.CurrentUICulture = culture;
            }

        });

    }
}

要发送或不发送响应的位置立即取决于HttpContext.Current.Response.BufferOutput值。如果为true,则下一个直接插入的中间件可能会清除缓冲区并重新开始。如果为假,则将数据发送到线路。

答案 1 :(得分:0)

是的,事实上,当我们制造中间件时,我们有可能实现这一目标。

这是自定义中间件:

public class MyCustomMiddleware
{
    private readonly RequestDelegate _next;

    public CustomMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        //do sth

        //line below writes response
        await context.Response.WriteAsync($"Hello");

        //do sth

        //line below passes request to next middleware
        await _next(httpContext);

        //do sth
    }
}

请注意,您可以省略await context.Response.WriteAsync(xxx);await _next(httpContext);

如果省略await _next(httpContext);,该请求将不会传递到下一个中​​间件。

中间件可以开始响应请求,然后可以决定是否将请求传递给下一个中间件。 如果中间件尝试使用Response.WriteAsync()写入已响应请求的响应主体,则会发生异常。

如果我们要使用别人编写的中间件,我们必须了解它们。

Write Custome ASP.NET Core Middleware 该页面详细介绍了如何创建中间件。