Welcome to YARP - 5.壓縮、緩存

来源:https://www.cnblogs.com/condding-y/archive/2023/11/13/17828298.html
-Advertisement-
Play Games

目錄 Welcome to YARP - 1.認識YARP並搭建反向代理服務 Welcome to YARP - 2.配置功能 2.1 - 配置文件(Configuration Files) 2.2 - 配置提供者(Configuration Providers) 2.3 - 配置過濾器(Confi ...


目錄

Welcome to YARP - 1.認識YARP並搭建反向代理服務

Welcome to YARP - 2.配置功能

Welcome to YARP - 3.負載均衡

Welcome to YARP - 4.限流

Welcome to YARP - 5.身份驗證和授權

Welcome to YARP - 6.壓縮、緩存

Welcome to YARP - 7.健康檢查

Welcome to YARP - 8.分散式跟蹤

介紹

網關的 緩存壓縮是常見的性能優化手段 ,用於提高系統的響應速度和降低網路傳輸的開銷。

YARP 的 緩存壓縮 其實也是 .NET 本身的功能。只需要配置 .NET 本身的緩存和壓縮功能即可。

緩存

緩存的主要目的是優化性能、提高效率,減少對後端服務的負擔。 我們可以對

頻繁請求的靜態數據或不經常更改的數據 進行 API 緩存,從而降低對後端服務的請求次數,提高響應速度,減輕後端服務的負載。

也可以對 靜態資源 緩存 如:css、js、圖像等,從而 加速頁面載入速度,減輕伺服器壓力,提高用戶體驗。 等等。

基於 HTTP 的響應緩存

用於緩存的主 HTTP 標頭是 Cache-Control,它用於指定緩存指令。 當請求從客戶端到達伺服器以及響應從伺服器返回客戶端時,這些指令控制緩存行為。 請求和響應在代理伺服器之間移動,並且代理伺服器還必須符合 HTTP 1.1 緩存規範。

Cache-Control 通用消息頭欄位,被用於在 http 請求和響應中,通過指定指令來實現緩存機制。緩存指令是單向的,這意味著在請求中設置的指令,不一定被包含在響應中。

要使用緩存,請求頭中必須攜帶 Cache-Control 標頭。同時響應頭中也要做相應的設置。

下表中顯示了常用 Cache-Control 指令

指令 操作
public 緩存可以存儲響應。
private 響應不得由共用緩存存儲。 專用緩存可以存儲和重用響應。
max-age 客戶端不接受期限大於指定秒數的響應。 示例:max-age=60(60 秒),max-age=2592000(1 個月)
no-cache 請求時:緩存不能使用存儲的響應來滿足請求。 源伺服器重新生成客戶端的響應,中間件更新其緩存中存儲的響應。 響應時:響應不得用於未經源伺服器驗證的後續請求。
no-store 請求時:緩存不得存儲請求。 響應時:緩存不得存儲任何部分的響應。

相應的我們也要添加響應緩存中間件:

若要測試響應緩存,請使用 Fiddler、Postman 或其他可以顯式設置請求標頭的工具。顯式設置上述的請求標頭。

配置中間件

在 中 Program.cs ,將響應緩存中間件服務 AddResponseCaching 添加到服務集合中,並將應用配置為將中間件與 UseResponseCaching 擴展方法一起使用。 UseResponseCaching 將中間件添加到請求處理管道中:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddReverseProxy()//添加ReverseProxy相關服務到DI
    .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));//從配置文件中載入ReverseProxy的設置

builder.Services.AddResponseCaching(options =>
{
    options.UseCaseSensitivePaths = false; //確定是否將響應緩存在區分大小寫的路徑上。 
    options.SizeLimit = options.SizeLimit * 10; // 響應緩存中間件的大小限制(以位元組為單位) 1G
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

// 使用 CORS 中間件時,必須在 UseResponseCaching 之前調用 UseCors。
// app.UseCors();
app.UseRouting();

// 攔截請求並判斷 請求頭中是否包含 CacheControl 標頭,如果沒有則加上緩存標頭
app.Use(async (context, next) =>
{
    var header = context.Request.Headers;
    var cacheControl = header.CacheControl;
    if (!string.IsNullOrEmpty(header.CacheControl))
    {
        header.CacheControl = new Microsoft.Extensions.Primitives.StringValues("max-age");
    }

    await next(context);
});
app.UseResponseCaching();
app.Use(async (context, next) =>
{
    context.Response.GetTypedHeaders().CacheControl =
        new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
        {
            Public = true,
            MaxAge = TimeSpan.FromSeconds(10)
        };

    context.Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.Vary] = new string[] { "Accept-Encoding" };

    await next(context);
});
app.MapReverseProxy();

app.MapGet("/", () => DateTime.Now.ToLongTimeString());

app.Run();

以上示例中:

  • Cache-Control:緩存可緩存響應長達10秒。
  • Vary:將中間件配置為僅當後續請求的 Accept-Encoding 標頭與原始請求頭匹配時才提供緩存的響應。

app.Use(async (context, next) =>
{
var header = context.Request.Headers;
var cacheControl = header.CacheControl;
if (!string.IsNullOrEmpty(header.CacheControl))
{
header.CacheControl = new Microsoft.Extensions.Primitives.StringValues("max-age");
}

await next(context);

});

可以看到我們先設置了 請求頭的 緩存標頭,如果 沒有此 設置,幾乎所有瀏覽器(標頭值)都會發送 CacheControl:no-cache 或其他值,強制執行非緩存頁面請求,這會導致 ResponseCachingMiddleware 實現忽略此請求(忽略緩存)並將其傳遞到伺服器以檢索數據。 如果你用 postman 或者 fiddle則可以主動這隻CacheControl標頭值為上述說的那幾種。

上述示例中我們先 添加了 YARP 服務,然後添加了 AddResponseCaching 響應的緩存服務,然後攔截了請求並設置緩存標頭,再開啟了 UseResponseCaching() 響應緩存中間件。接下來設置了 [響應頭的標頭值]( ASP.NET Core 中的響應緩存中間件 | Microsoft Learn ),最後開啟了 代理 中間件。源碼已上傳GitHub.

壓縮

網路帶寬是一種有限資源。 減小響應大小通常可顯著提高應用的響應速度。 減小有效負載大小的一種方式是壓縮應用的響應。 但是 YARP 預設是禁用解壓縮的,因為它會增加 CPU 開銷。

什麼時候使用 響應壓縮 中間件?

在 IIS、Apache 或 Nginx 中使用基於伺服器的響應壓縮技術。

而 HTTP.sys 伺服器和 Kestrel 伺服器當前不提供內置壓縮支持,這時候就需要使用響應壓縮中間件了。

我們使用 YARP 的直接轉發來 演示一下 壓縮功能,當然壓縮是 .NET 本身自帶的功能,你也可以通過添加壓縮中間件來開啟響應壓縮。

代碼示例:

using System.Diagnostics;
using System.Net;
using Yarp.ReverseProxy.Forwarder;
using Yarp.ReverseProxy.Transforms;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpForwarder();

// Add services to the container.

var app = builder.Build();

// Configure our own HttpMessageInvoker for outbound calls for proxy operations
var httpClient = new HttpMessageInvoker(new SocketsHttpHandler()
{
    UseProxy = false,
    AllowAutoRedirect = false,
    AutomaticDecompression = DecompressionMethods.GZip, // 設置響應壓縮方式
    UseCookies = false,
    ActivityHeadersPropagator = new ReverseProxyPropagator(DistributedContextPropagator.Current),
    ConnectTimeout = TimeSpan.FromSeconds(15),
});

// Setup our own request transform class
var transformer = new CustomTransformer(); // or HttpTransformer.Default;
var requestConfig = new ForwarderRequestConfig { ActivityTimeout = TimeSpan.FromSeconds(100) };

app.UseRouting();

// Configure the HTTP request pipeline.

app.MapForwarder("/{**catch-all}", "http://localhost:5047", requestConfig, transformer, httpClient);

app.Run();

/// <summary>
/// 自定義請求轉換
/// </summary>
class CustomTransformer : HttpTransformer
{
    ///<summary>
    /// A callback that is invoked prior to sending the proxied request. All HttpRequestMessage
    /// fields are initialized except RequestUri, which will be initialized after the
    /// callback if no value is provided. The string parameter represents the destination
    /// URI prefix that should be used when constructing the RequestUri. The headers
    /// are copied by the base implementation, excluding some protocol headers like HTTP/2
    /// pseudo headers (":authority").
    ///</summary>
    ///<param name="httpContext">傳入請求</param>
    ///<param name="proxyRequest">傳出的代理請求</param>
    ///<param name="destinationPrefix">所選目標伺服器的uri首碼,可用於創建RequestUri</param>
    public override async ValueTask TransformRequestAsync(HttpContext httpContext, HttpRequestMessage proxyRequest, string destinationPrefix, CancellationToken cancellationToken)
    {
        // 轉發所有頭部信息
        await base.TransformRequestAsync(httpContext, proxyRequest, destinationPrefix, cancellationToken);
        // 自定義查詢query 值
        var queryContext = new QueryTransformContext(httpContext.Request);
        queryContext.Collection.Remove("param1");
        queryContext.Collection["s"] = "xx2";
        // 分配自定義 URI。在此處連接時請註意額外的斜杠。RequestUtilities.MakeDestinationAddress 是一個安全的預設值。
        proxyRequest.RequestUri = RequestUtilities.MakeDestinationAddress("http://localhost:5047", httpContext.Request.Path, queryContext.QueryString);
        // 禁止原始請求標頭,使用目標 Uri 中的標頭
        proxyRequest.Headers.Host = null;
    }
}

上述示例中,我們使用了 YARP 的直接轉發模式,不需要添加 YARP 服務和中間件,但是要添加 這個東西 AddHttpForwarder,然後配置 自定義請求轉換 類。並開啟 壓縮模式為 GZip。

如果想看效果記得使用fiddle 抓取請求的返回值查看原始請求,因為postman和瀏覽器客戶端 都會預設對常用的壓縮格式的數據進行解壓縮。

如果伺服器本身支持壓縮,請使用 基於伺服器的壓縮技術。而 HTTP.sys 伺服器和 Kestrel 伺服器 是不支持壓縮技術的,所以這時候才考慮使用 壓縮中間件。

總結

本章我們介紹了 YARP 的緩存和壓縮功能,其實也都是 .NET 自身的功能,如果瞭解使用過 .NET的 緩存 和 壓縮 中間件很容易就能理解。本章示例代碼已上傳GitHub,建議把代碼down下來自己實驗一下,再去配合理解。

有什麼問題歡迎留言交流。

下篇文章我們繼續介紹 YARP 的健康檢查功能。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 操作系統 :Windows 10_x64 python版本 :3.9.2 pymysql版本: 1.0.2 MySQL版本: 5.7.38 之前寫過一篇關於python操作mysql資料庫的文章: https://www.cnblogs.com/MikeZhang/p/pythonOptMysql2 ...
  • 寫在前面 目前已經上班快兩個月了,對現在的工作很滿意,甚至更喜歡這的氛圍吧。 如題所示,從今年5月開始,發生的所有事,都完全超出了我自己可以承受的範圍,好在這一切都過去了,真的感謝上天安排,讓我能更加確信自己要的是什麼,以後該怎麼生活。 爸爸被診斷為肺癌 我每年都會帶父母去做體檢,因為去年疫情全面放 ...
  • 本文適用範圍 主要適用於debug python 程式,尤其是深度學習剛入門需要使用remote 連接到linux進行程式運行,想調試一下的同學。 當然非深度學習也可以參考食用本文哈哈哈。 極速入門版 提前準備:代碼倉庫已經拉取到linux上面,且已經知道運行的方式。 比如: 項目的啟動命令為:py ...
  • 五、位運算 ​ 位運算主要計算記憶體中每個小格的數據 1、輸出二進位內容 頭文件調用 語法 示例 include <bitser> std::bitset<要顯示的二進位位數>(要顯示的變數) std::cout << std::bitset<16>(a); //二進位內容輸出 #include <i ...
  • 在 Java 中,有四種方法可以獲取當前正在執行方法體的方法名稱,分別是: 使用 Thread.currentThread().getStackTrace() 方法 使用異常對象的 getStackTrace() 方法 使用匿名內部類的 getClass().getEnclosingMethod() ...
  • Guava 是 Google 提供的一套 Java 工具包,而 Guava Cache 是該工具包中提供的一套完善的 JVM 級別高併發緩存框架;本文主要介紹它的相關功能及基本使用,文中所使用到的軟體版本:Java 1.8.0_341、Guava 32.1.3-jre。 1、簡介 緩存在很多情況下非 ...
  • Python安裝之後,其標準庫中有的模塊,不一定要通過代碼來引用,還可以直接在命令行中使用的。 在命令行中直接使用Python標準庫的模塊,最大的好處就是就是不用寫代碼,就能使用其中的功能,當臨時需要一些某些功能的時候,用這種方式會快捷,方便很多。 1. 命令行中使用模塊 命令行中使用python標 ...
  • 四、基本數據類型和計算(三) 1、枚舉變數 1)通過案例體現枚舉類型的作用 ​ 假設要為我們的游戲裝備設置稀有度屬性,應該如何設計 裝備級別 變數名 普通 normal 高級 high 稀有 rare 史詩 epic 傳說 legend 神話 myth 不使用枚舉變數,使用常量方式設置 #inclu ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...