asp.net core 系列之Performance的 Response compression(響應壓縮)


本文,幫助了解響應壓縮的一些知識及用法(大部分翻譯於官網,英文水平有限,不准確之處,歡迎指正)。

什么是響應壓縮?響應壓縮簡單的說就是為了減少網絡帶寬,而把返回的響應壓縮,使之體積縮小,從而加快響應的一種技術(個人理解)

網絡帶寬是有限的資源。減少響應(response)的大小通常可以增加應用的響應性(即減少響應的大小可以加快響應的速度),這是很引人注目的(often dramatically).壓縮(壓縮compress)應用的響應可以減少裝載的大小。

當使用響應壓縮中間件時(Response Compression Middleware)

在IIS,ApacheNginx中使用基於服務端的響應壓縮技術。中間件的執行可能和服務端模塊不匹配。HTTP.sys Kestrel server目前沒有提供內置的壓縮支持。

什么時候使用Response Compression Middleware:

  • 不能使用下面的服務端壓縮技術時:
    • IIS Dynamic Compression module (IIS 動態壓縮模塊)
    • Apache mod_deflate module (deflate:緊縮 )
    • Nginx Compression and Decompression
  • 部署運行在:
    • HTTP.sys server
    • Kestrel server

響應壓縮(Response compression)

通常,任何不能自動壓縮的響應都可以從響應壓縮中獲益。典型的不能自動壓縮的響應包括:CSS, JavaScript, HTML, XML, 和JSON. 你不應該壓縮自動壓縮的文件,例如 PNG文件。如果你嘗試更進一步壓縮一個自動壓縮的響應,那么任何小的額外的縮小和傳送時間都將會顯得黯然失色,等到它處理壓縮, 不要壓縮小於150-1000bytes文件(取決於文件的內容和壓縮的效率)壓縮小文件開銷可以產生大於未壓縮文件的壓縮文件

當客戶端可以處理壓縮內容時,客戶端必須通過發送請求頭上的Accept-Encoding 通知服務器它的能力。當服務器發送壓縮內容時,它必須在Content-Encoding 頭中包含壓縮的響應是怎么編碼的內容。內容編碼的指定是通過下表中展示的中間件支持的。

中間件允許你為自定義的Accept-Encoding 的頭上的值增加額外的壓縮提供者,中間件對於質量值的反應是很熟練的,質量值是被客戶端發送的用來衡量優先處理壓縮協議的。

壓縮算法是受支配於壓縮速度和壓縮效率的一種平衡交易。效率關系到壓縮之后的大小,最優壓縮壓縮出來的就是最小的。

涉及到請求,發送,緩存,接收壓縮內容的頭部在下表中有描述

 

利用sample app 探索響應壓縮的功能。這個例子表明:

  •  應用的利用Gzip和自定義壓縮提供者的壓縮
  • 怎樣增加MIME類型到默認的壓縮的MIME類型的列表

Package

為了在項目中包含這個中間件,增加一個到 Microsoft.AspNetCore.App metapackage, 的引用,它包含 Microsoft.AspNetCore.ResponseCompression 包 

Configuration

下面的代碼展示了怎樣允許Response Compression Middleware , 對於默認的MIME類型和壓縮提供者(Brotli Gzip):

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddResponseCompression();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseResponseCompression();
    }
} 

注意:

  • App.UseResponseCompression 必須在app.UseMvc之前被調用

  • 用一個工具(例如Fiddler, Filrebug, Postman)來設置Accept-Encoding 請求頭,並且研究響應頭,大小和body

提交一個不攜帶Acccept-Encoding 頭的請求到示例應用,並且觀察到響應是未壓縮的。Content-Encoding 和 Vary 頭沒有在響應中呈現。

 

提交一個帶Accept-Encoding: br頭的請求到示例應用。(Brotli compress)並且觀察響應是壓縮的。Content-Encoding Vary 在響應中呈現了。

Providers(提供者)

Brotli Compression Provider

使用BrotliCompressionProvider來壓縮響應,使用Brotli compressed data format ( brotli compress 數據格式),

如果沒有compression providers(壓縮提供者)被明確的加到 CompressionProviderCollection中:

  • Brotli Compression Provider 默認被加到compression providers的數組中,和Gzip compression provider.
  • 當客戶端支持Brotli compressed data format (Brotli 壓縮數據格式)時,默認使用Brotli compression 壓縮. 如果客戶端不支持Brotli , 但是客戶端支持Gzip 壓縮時,會默認使用Gzip
public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCompression();
}

Brotoli Compression Provider必須被添加,當任意compression provider 明確的被添加時。

public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCompression(options =>
    {
        options.Providers.Add<BrotliCompressionProvider>();
        options.Providers.Add<GzipCompressionProvider>();
        options.Providers.Add<CustomCompressionProvider>();
        options.MimeTypes = 
            ResponseCompressionDefaults.MimeTypes.Concat(
                new[] { "image/svg+xml" });
    });
}

使用BrotliCompressionProviderOptions設置壓縮級別。Brotli Compression Provider默認使用的是最快的壓縮級別( CompressionLevel.Fastest ), 這種級別可能不會產生最有效率的壓縮。如果最有效率的壓縮被需要時,可以為最佳的壓縮配置中間件

public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCompression();

    services.Configure<BrotliCompressionProviderOptions>(options => 
    {
        options.Level = CompressionLevel.Fastest;
    });
}

Gzip Compression Provider

使用GzipCompressionProvider來壓縮響應,用Gzip file format.(用Gzip 文件格式)

如果沒有compression provider被明確的加入到CompressionProviderCollection中:

  • Gzip Compression Provider默認被添加到 壓縮提供者數組中,並且還有Brotli Compression Provider.
  • 當客戶端支持Brotli compressed data format (Brotli 壓縮數據格式)時,默認使用Brotli compression 壓縮. 如果客戶端不支持Brotli , 但是客戶端支持Gzip 壓縮時,會默認使用Gzip 
public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCompression();
}

Gzip Compression Provider 必須被添加,當任意壓縮提供者被明確的添加時:

public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCompression(options =>
    {
        options.Providers.Add<BrotliCompressionProvider>();
        options.Providers.Add<GzipCompressionProvider>();
        options.Providers.Add<CustomCompressionProvider>();
        options.MimeTypes = 
            ResponseCompressionDefaults.MimeTypes.Concat(
                new[] { "image/svg+xml" });
    });
} 

使用GzipCompressionProviderOptions設置壓縮級別。Gzip Compression Provider默認使用的是最快的壓縮級別( CompressionLevel.Fastest ), 這種級別可能不會產生最有效率的壓縮。如果最有效率的壓縮被需要時,可以為最佳的壓縮配置中間件

public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCompression();

    services.Configure<GzipCompressionProviderOptions>(options => 
    {
        options.Level = CompressionLevel.Fastest;
    });
}

Custom providers

通過實現ICompressionProvider接口創建自定義的壓縮。EncodingName代表ICompressionProvider生成的內容編碼(the content encoding). 中間件使用這個信息來選擇provider,在請求的Accept-Encoding 頭上的列表的基礎上。

在示例項目上,客戶端提交請求,帶有Accept-Encoding: mycustomcompression頭。中間件使用自定義的壓縮實現並且返回帶有Content-Encoding:mycustomcompression頭的響應。客戶端必須可以按順序的解壓自定義的編碼( the custom encoding) ,對於一個自定義的壓縮實現的工作。

public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCompression(options =>
    {
        options.Providers.Add<BrotliCompressionProvider>();
        options.Providers.Add<GzipCompressionProvider>();
        options.Providers.Add<CustomCompressionProvider>();
        options.MimeTypes = 
            ResponseCompressionDefaults.MimeTypes.Concat(
                new[] { "image/svg+xml" });
    });
}
public class CustomCompressionProvider : ICompressionProvider
{
    public string EncodingName => "mycustomcompression";
    public bool SupportsFlush => true;

    public Stream CreateStream(Stream outputStream)
    {
        // Create a custom compression stream wrapper here
        return outputStream;
    }
}

提交一個帶Accept-Encodign:mycustomcompression頭的請求到示例應用,並且觀察響應頭。響應中呈現出了Vary Content-Encoding頭。The response body 沒有被壓縮在項目中。在示例項目的CustomCompressionProvider類中沒有一個壓縮實現。示例展示了你在哪里實現這樣一個壓縮算法。

MIME types

這個中間件指定一個默認的用於壓縮的MIME types:

  • application/javascript
  • application/json
  • application/xml
  • text/css
  • text/html
  • text/json
  • text/plain
  • text/xml

在Response Compression Middleware options上替換或者增加MIME types. 注意,帶有通配符的MIME types, 例如 text/* 是不支持的。 示例應用中增加了一個MIME type image/svg+xml 並且壓縮並且作用於ASP.NET Corebanner image ( banner,svg ).

public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCompression(options =>
    {
        options.Providers.Add<BrotliCompressionProvider>();
        options.Providers.Add<GzipCompressionProvider>();
        options.Providers.Add<CustomCompressionProvider>();
        options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat( new[] { "image/svg+xml" });
    });
}

Compression with secure protocol (帶安全協議的壓縮)

在安全連接上的壓縮響應可以使用 EnableForHttps 項(option)來控制, 它默認是被禁用的, 在動態生成的頁面上面使用壓縮可能會導致安全問題, 例如  CRIME and BREACH  攻擊。

Adding the Vary header

當壓縮響應在Accept-Encoding 頭上時, 那是可能會有多個壓縮版本(compressed versions)的響應和一個不壓縮的版本。為了指導客戶端和代理(client and proxy)緩存多個存在的版本,並且存儲,Vary 頭是被加到Accept-Encoding 值。 在ASP.NET Core 2.0或者更新的版本,當響應被壓縮時,中間件自動添加Vary 頭。

Middleware issue when behind an Nginx reverse proxy (Nginx反向代理時中間件的問題)

當一個請求被Nginx代理時,Accept-Encoding 頭被移除了, Accept-Encoding頭的移除阻止了中間件壓縮響應。更多的信息:NGINX: Compression and Decompression

Working with IIS dynamic compression

當你有一個激活的IIS動態壓縮模塊配置在服務器級別(at the server level), 你可能會想要在一個應用上禁止它,那么你可以在web.config文件中禁用它。更多的信息:Disabling IIS modules.  

 本文翻譯於:https://docs.microsoft.com/en-us/aspnet/core/performance/response-compression?view=aspnetcore-2.2

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM