使用 HttpClient 压缩对 asp.net core 2 站点的请求的最佳方法是啥?

Posted

技术标签:

【中文标题】使用 HttpClient 压缩对 asp.net core 2 站点的请求的最佳方法是啥?【英文标题】:What is the best way to compress a request to asp.net core 2 site using HttpClient?使用 HttpClient 压缩对 asp.net core 2 站点的请求的最佳方法是什么? 【发布时间】:2017-10-09 20:37:09 【问题描述】:

我发送的请求可能非常大(~1Mb),并且在我发出请求和 asp.net 核心记录它正在处理请求之间出现很大延迟。我想我可以通过使用 gzip 将请求压缩到 asp 来减少这个时间。

以下是我在不压缩的情况下发出请求的相当直接的方式。在客户端请求端实现Gzip请求压缩的正确方法是什么,一旦我在客户端实现它,我需要为服务器端做什么?

using (HttpResponseMessage response = client.PostAsync("Controller/Action", httpContent).Result)

    if (response.StatusCode != System.Net.HttpStatusCode.OK)
    

        throw new Exception(string.Format("Invalid responsecode for http request response 0: 1", response.StatusCode, response.ReasonPhrase));
    

【问题讨论】:

【参考方案1】:

所以我让它在服务器端使用简单的中间件,而不是在客户端做太多工作。我使用了CompressedContent.cs from WebAPIContrib,正如雷克斯在他的回答中建议的那样,并提出了如下所示的请求。整个 throw-exception-if-not-OK 是因为我使用 Polly 包裹我的请求,并带有重试和等待策略。

客户端:

using (var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json"))
using (var compressedContent = new CompressedContent(httpContent, "gzip"))
using (HttpResponseMessage response = client.PostAsync("Controller/Action", compressedContent).Result)

    if (response.StatusCode != System.Net.HttpStatusCode.OK)
    
        throw new Exception(string.Format("Invalid responsecode for http request response 0: 1", response.StatusCode, response.ReasonPhrase));
    

然后在服务器端,我创建了一个简单的中间件,它将请求主体流与 Gzip 流包装在一起。要使用它,您需要在Startup.csConfigure 方法中添加app.UseMiddleware<GzipRequestMiddleware>();app.UseMvc(); 的调用。

public class GzipRequestMiddleware

    private readonly RequestDelegate next;
    private const string ContentEncodingHeader = "Content-Encoding";
    private const string ContentEncodingGzip = "gzip";
    private const string ContentEncodingDeflate = "deflate";

    public GzipRequestMiddleware(RequestDelegate next)
    
        this.next = next ?? throw new ArgumentNullException(nameof(next));
    

    public async Task Invoke(HttpContext context)
    
        if (context.Request.Headers.Keys.Contains(ContentEncodingHeader) && (context.Request.Headers[ContentEncodingHeader] == ContentEncodingGzip || context.Request.Headers[ContentEncodingHeader] == ContentEncodingDeflate))
        
            var contentEncoding = context.Request.Headers[ContentEncodingHeader];
            var decompressor = contentEncoding == ContentEncodingGzip ? (Stream)new GZipStream(context.Request.Body, CompressionMode.Decompress, true) : (Stream)new DeflateStream(context.Request.Body, CompressionMode.Decompress, true);
            context.Request.Body = decompressor;
        
        await next(context);
    

【讨论】:

【参考方案2】:

您可能需要启用压缩,如下所示

var handler = new HttpClientHandler();  
if (handler.SupportsAutomaticDecompression)  

    handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;


var client = new HttpClient(handler);  

MSDN 参考:Using automatic decompression with HttpClient

【讨论】:

最好有一个 msdn 参考链接 blogs.msdn.microsoft.com/dotnet/2013/06/06/… 也许我遗漏了一些东西,但看起来它只会处理响应解压缩而不是请求压缩,对吧? @Theyouthis - 对。这会在从客户端到服务器的请求中添加额外的 Accept-Encoding 标头,指示服务器支持压缩响应。但是要启用压缩请求,则可以使用 WebAPIContrib 中的 CompressedContent 类来完成,框架***.com/a/16674884/7630979 的限制很少

以上是关于使用 HttpClient 压缩对 asp.net core 2 站点的请求的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC 4 HttpClient() 问题

如何在使用 HttpClient 使用 Asp Net Web Api 的 Asp Net Mvc 中提供实时数据?

ASP.NET下使用Combres对JSCSS压缩合并和优化

在 ASP.NET Core 应用程序中使用多个 HttpClient 对象

如何在ASP.NET Core 中使用IHttpClientFactory

asp.net core 使用HttpClientFactory Polly实现熔断降级