ASP.NET Core文(wen)件壓縮最佳實踐(jian)
前言
在微(wei)軟官方文檔(dang)中,未明確(que)指出(chu)文件壓縮(suo)功能的(de)使用誤區。
本文將對 ASP.NET Core 文件響(xiang)應壓縮的常(chang)見使用誤區做出說明。
誤區1:未使用 Brotil 壓縮
幾乎不(bu)需要任何額(e)外的代價,Brotil 壓縮算法可以幫助(zhu)你的網站(zhan)提升約 20% 靜態資源加載性能。
同時啟用 Gzip / Brotil 壓縮
Gzip 有更好的 user-agent 兼容性(xing),而 Brotli 有更好的性(xing)能(neng)。
所以我(wo)們通常需要在 ASP.NET Core 網站中(zhong)同時啟用這兩種(zhong)壓縮。
如何區分 Gzip 壓縮和 Brotli 壓縮
網站啟(qi)用 Brotli 壓縮時,服(fu)務器請求返(fan)回頭 Content-Encoding 中會(hui)包含 br 字樣,否則是 gzip。
誤區2:使用 Fastest 級別的 Brotli 壓縮
如(ru)果你閱(yue)讀并參考了微軟(ruan)官方文檔(dang)或(huo)者其(qi)他(ta)中(zhong)文資源(yuan),比如(ru):
- MS Doc
在ASP.NET Core中使用brotli壓縮 - Cnblogs
那(nei)么你可能會在代(dai)碼中像下面這樣(yang)使用壓縮功能:
寫法1:使用默認的壓縮行為(框架將(jiang)隱式添加 Brotli 和 Gzip 功能)
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddResponseCompression(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseResponseCompression(); } }
寫法2:顯式添加壓縮功能
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" }); }); services.Configure<BrotliCompressionProviderOptions>(options => { options.Level = CompressionLevel.Fastest; }); }
寫法3:自定義 BrotliCompressionProvider
public class BrotliCompressionProvider : ICompressionProvider { public string EncodingName => "br"; public bool SupportsFlush => true public Stream CreateStream(Stream outputStream) { return new BrotliStream(outputStream,CompressionLevel.Fastest); } }
不(bu)幸的是,以上三種(zhong)寫法都沒有發揮出 Brotil 壓縮算法的優勢(shi)。
它們(men)的共同點是均(jun)使(shi)用了(le) CompressionLevel.Fastest 壓(ya)縮級別。
而在 CompressionLevel.Fastest 級別時,Brotil 與 Gzip 壓縮性能幾乎無異。
參考:

圖 2-1 Fastest 模式(shi)下(xia),三種算法的(de)壓縮率等同
誤區3:使用 Optimal 級別的 Brotli 壓縮
CompressionLevel 只有三個枚舉值:Fastest / NoCompression / Optimal。
既然 Fastest 級別(bie)沒(mei)有用,那我們只(zhi)能換成 Optimal 了。

圖 3-1 壓縮(suo)級別枚舉
試后就會發現,Brotil 的 Optimal 壓縮級別存在嚴重的性能問題,在實(shi)際網站應用中幾乎沒有(you)適(shi)用的場景。

圖(tu) 3-2 Optimal 壓縮耗時對比
最佳實踐:使用 5 或 6 級別的 Brotli 壓縮
在 這篇文章中,作者對(dui)不同級別 Brotil 的壓縮(suo)耗時做了(le)評測,也(ye)就是下面這幅圖。

圖 4-1 不同壓縮(suo)級別下 Brotli 的(de)壓縮(suo)耗時(shi)
觀察這副圖,Brotil 的壓縮質量其實有 1~11 個級別。
那我們如何自定義 Brotli 的壓縮級別呢,答案是直接將級別對應的整數轉成 CompressionLevel 枚舉。
參考:

圖 4-2 指定(ding) Brotli 的(de)壓縮級別
盡管(guan)這種(zhong)寫(xie)法看起來十(shi)分古(gu)怪,但通(tong)過考察 .NET 源(yuan)碼,可(ke)以確鑿這種(zhong)寫(xie)法是可(ke)行的。
參考:

圖 4-3 CompressionLevel 枚舉強制轉換整數(shu)
現在我們可以自定義壓縮級別了,但注意上方源碼,只能指定 3 以上的級別,3 包括 3 以下(xia)的(de)值(zhi)有其他對(dui)應的(de)轉換(huan)邏輯(ji)。
回到本節(jie)第一副圖 4-1,通過實測(ce),發(fa)現在(zai) 5 / 6 級(ji)別下,Brotli 確(que)實可以獲得最佳的(de)壓縮率和較低的(de)壓縮損耗。
總結
在 ASP.NET Core 中,我(wo)們應(ying)(ying)該同(tong)時(shi)啟用 Gzip 和(he) Brotil 壓縮功能,其中 Brotil 的壓縮級別應(ying)(ying)該自定義(yi)到 5 或(huo) 6。
public void ConfigureServices(IServiceCollection services) { services.AddResponseCompression(options => { options.Providers.Add<BrotliCompressionProvider>(); options.Providers.Add<GzipCompressionProvider>(); options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat( new[] { "image/svg+xml" }); }); services.Configure<BrotliCompressionProviderOptions>(options => { options.Level = (CompressionLevel)5; // 5 or 6 is OK }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseResponseCompression(); }