[料理佳餚] 啟用 gRPC 服務的壓縮(Compression)機制讓傳輸量少還要更少

gRPC 服務底層使用 Protocol Buffers 做為序列化的格式,與我們經常使用的 JSON 格式相比之下,其大小已經小非常多了,如果我們還覺得不夠,想要再更進一步地減少傳輸量,可以啟用 gRPC 服務的壓縮(Compression)機制,讓傳輸的資料量再更少一些。

ResponseCompressionLevel

啟用壓縮機制的方式非常簡單,在伺服器端 Startup.csConfigureServices() 方法裡面呼叫 AddGrpc() 時,指定 ResponseCompressionLevelResponseCompressionAlgorithm 的值。

public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc(
        grpcOptions =>
            {
                grpcOptions.ResponseCompressionLevel = CompressionLevel.Optimal;
                grpcOptions.ResponseCompressionAlgorithm = "gzip";
            });
}

ResponseCompressionLevel 有三個值可以選,分別是:OptimalFastestNoCompression,而 ResponseCompressionAlgorithm 則是根據 CompressionProviders 中有的壓縮演算法來指定, gRPC 服務預設提供的只有 Gzip 壓縮演算法。

這樣做,壓縮機制就算是啟用完畢了,Client 端都不用改。

服務層級的壓縮

上述的設定方式是屬於全域設定,一設定之後所有的服務都會套用,如果只想針對單一個服務啟用壓縮機制,須改用 AddServiceOptions() 方法。

public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc()
        .AddServiceOptions<EmployeeService>(
            grpcOptions =>
                {
                    grpcOptions.ResponseCompressionLevel = CompressionLevel.Optimal;
                    grpcOptions.ResponseCompressionAlgorithm = "gzip";
                });
}

服務方法層級的壓縮

想再更精確地控制到某個服務方法才啟用壓縮機制,這個需要搭配啟用「服務層級的壓縮」之後,在不需要壓縮機制的服務方法內,變更其回應的 WriteOptions 值為 NoCompress

客戶端單方面關閉壓縮

通常我們會把壓縮這件事情設定在伺服器端,客戶端只能被動接受,但是某些客戶端的情境會希望不要使用壓縮,gRPC 服務也允許我們在客戶端將其關閉,我們只要在建立 Channel 的時候將 CompressionProviders 清空就行了。

看看差了多少?

為了看出差異,我請出了老牌的網路監控工具 - Network Monitor,以我的範例來看,在還沒壓縮前整個傳輸量在 3500 bytes 左右。

啟用最佳壓縮之後,降到了 350 bytes 左右。

然而,壓縮這件事並不是免費的午餐,它會讓伺服器端及客戶端多一點 CPU 的消耗,因此要不要使用壓縮,我們必須加以衡量,看看我們的資料中,重複性的內容是不是很多?測試看看啟用前後的回應速度是不是如我們預期?做好完整的驗證之後,再來決定是否應該使用壓縮。

參考資料

C# 指南 ASP.NET 教學 ASP.NET MVC 指引
Azure SQL Database 教學 SQL Server 教學 Xamarin.Forms 教學