.Net Core HttpClient處理響應壓縮
阿新 • • 發佈:2020-08-04
### 前言
在上篇文章[[ASP.NET Core中的響應壓縮](https://www.cnblogs.com/wucy/p/13395674.html)]中我們談到了在ASP.NET Core服務端處理關於響應壓縮的請求,服務端的主要工作就是根據Content-Encoding頭資訊判斷採用哪種方式壓縮並返回。之前在群裡有人問道過,現在的網路頻寬這麼高了還有必要在服務端針對請求進行壓縮嗎?確實,如今分散式和負載均衡技術這麼成熟,很多需要處理高併發大資料的場景都可以通過增加伺服器節點來進行。但是,在資源受限的情況下,或者是還沒必要為了某一個點去增加新的伺服器節點的時候,我們還是要採用一些程式本身的常規處理手段來進行處理。筆者個人認為響應壓縮的使用場景是這樣的,在頻寬壓力比較緊張的情況,且CPU資源比較充足的情況下,使用響應壓縮整體效果還是比較明顯的。
有壓縮就有解壓,而解壓的工作就是在請求客戶端處理的。比如瀏覽器,這是我們最常用的Http客戶端,許多瀏覽器都是預設在我們發出請求的時候(比如我們瀏覽網頁的時候)在Request Head中新增Content-Encoding,然後根據響應資訊處理相關解壓。這些都源於瀏覽器已經內建了關於請求壓縮和解壓的機制。類似的還有許多,比如常用的代理抓包工具Filder也是內建這種機制的。只不過需要手動去處理,但實現方式都是一樣的。有時候我們在自己寫程式的過程中也需要使用這種機制,在傳統的.Net HttpWebRequest類庫中,並沒有這種機制,後來版本中加入了HttpClient,有自帶的機制可以處理這種操作,.Net Core作為後起之秀直接將HttpClient扶正,並且在此基礎上改良了HttpClientFactory,接下來我們就來探究一下在.Net Core中使用HttpClient處理響應壓縮的機制。
### 使用方式
首先我們來看一下直接在HttpClient中如何處理響應壓縮
```cs
//自定義HttpClientHandler例項
HttpClientHandler httpClientHandler = new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip
};
//使用傳遞自定義HttpClientHandler例項的建構函式
using (HttpClient client = new HttpClient(httpClientHandler))
{
var response = await client.GetAsync($"http://MyDemo/Home/GetPerson?userId={userId}");
}
```
這個操作還是非常簡單的,我們操作的並不是HttpClient的屬性而是HttpClientHandler中的屬性,我們在之前的文章[[.NET Core HttpClient原始碼探究](https://www.cnblogs.com/wucy/p/12964869.html)]中曾探討過,HttpClient的本質其實就是HttpMessageHandler,而HttpClient真正使用到的是HttpMessageHandler最重要的一個子類HttpClientHandler,所有的請求操作都是通過HttpMessageHandler進行的。我們可以看到AutomaticDecompression接受的是DecompressionMethods列舉,既然是列舉就說明包含了不止一個值,接下來我們檢視DecompressionMethods中的原始碼
```cs
[Flags]
public enum DecompressionMethods
{
// 使用所有壓縮解壓縮演算法。
All = -1,
// 不使用解壓
None = 0x0,
// 使用gzip解壓演算法
GZip = 0x1,
// 使用deflate解壓演算法
Deflate = 0x2,
// 使用Brotli解壓演算法
Brotli = 0x4
}
```
該列舉預設都是針對常用輸出解壓演算法,接下來我們看一下在HttpClientFactory中如何處理響應壓縮。在之前的文章[[.NET Core HttpClientFactory+Consul實現服務發現](https://www.cnblogs.com/wucy/p/12941322.html)]中我們曾探討過HttpClientFactory的大致工作方式預設PrimaryHandler傳遞的就是HttpClientHandler例項,而且在我們註冊HttpClientFactory的時候是可以通過ConfigurePrimaryHttpMessageHandler自定義PrimaryHandler的預設值,接下來我們具體程式碼實現
```cs
services.AddHttpClient("mydemo", c =>
{
c.BaseAddress = new Uri("http://MyDemo/");
}).ConfigurePrimaryHttpMessageHandler(provider=> new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip
});
```
其實在註冊HttpClientFactory的時候還可以使用自定義的HttpClient,具體的使用方式是這樣的
```cs
services.AddHttpClient("mydemo", c =>
{
c.BaseAddress = new Uri("http://MyDemo/");
}).ConfigureHttpClient(provider => new HttpClient(new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip
}));
```
HttpClient確實幫我們做了好多事情,只需要簡單的配置一下就開啟了針對響應壓縮的處理。這更勾起了我們對HttpClient的探討,接下來我們就通過原始碼的方式檢視它是如何發起可響應壓縮請求,並解壓響應結果的。
### 原始碼探究
通過上面的使用方式我們得知,無論使用哪種形式,最終都是針對HttpClientHandler做配置操作,接下來我們檢視HttpClientHandler類[[點選檢視原始碼