簡體   English   中英

Azure API 管理刷新緩存響應

[英]Azure API Management refresh cached response

我將 API 管理與外部 Azure Redis 緩存一起使用來緩存訪問外部服務的響應。 我需要提供一種機制,通過從服務器重新獲取數據來使緩存的響應無效 - 反過來用新的響應更新緩存。

當緩存響應過期或收到帶有Cache-Control: must-revalidate標頭的新請求時,我當前的策略(如下所示)從服務器接收最新數據。 同樣,當收到標頭時,我想用新的響應更新緩存的響應。 我在概念上或政策中遺漏了什么嗎?

<policies>
    <inbound>
        <base />
        <set-backend-service id="apim-generated-policy" backend-id="func-myapp-dev-001" />
        <set-variable name="mustRevalidate" value="@(context.Request.Headers.GetValueOrDefault("Cache-Control","").Contains("must-revalidate"))" />
        <choose>
            <when condition="@(context.Variables.GetValueOrDefault<bool>("mustRevalidate") == false)">
                <cache-lookup vary-by-developer="false" vary-by-developer-groups="false" allow-private-response-caching="true" />
            </when>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
        <set-header name="Cached-At" exists-action="override">
            <value>@(System.DateTime.Now.ToString())</value>
        </set-header>
        <cache-store duration="360" />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

問題是<cache-store>不能沒有<cache-lookup> <cache-lookup>不僅從緩存中獲取緩存值,而且它也是<cache-store>一種配置。 您可以在跟蹤中親眼看到這一點。 不幸的是,當您使用Control-Cache: must-revalidate標頭調用 API 時, <cache-lookup>不會因為您的<when>策略而被觸發,但<cache-store>也不會被觸發。 在日志中,您將看到消息:

緩存存儲(0.019 毫秒)“未應用相應的緩存查找策略。跳過緩存存儲。”

所以你有它。 跳過<cache-lookup>將從后端獲得新的響應,但之后不會為將來的請求緩存它。


至於如何實現你想要的。

我已經檢查過兩次,但不幸的是<cache-lookup>沒有根據參數跳過查找的選項。

也在考慮不同的方法。 我認為這可以與<cache-lookup-value>策略一起使用。 一開始,根據您的must-revalidate參數,如果它設置為 true,您可以刪除緩存的值。 然后正常進行。 最難的部分是考慮可以根據請求生成緩存密鑰的機制。 APIM 在cache-store做同樣的事情。 密鑰在不同請求之間必須是唯一的,但對於同一請求必須相同 - 就像緩存工作一樣。 APIM 應用於緩存鍵的模式是這樣的(您可以檢查跟蹤):

"cacheKey": "{apimName}.{apiId};{revision};{backendurl with all query parameters}"

來自我的 API 的示例:

"cacheKey": "my-apim.azure-api.net.1_weatherbit-io;rev=1.2432_get-current-city_id-city_id-key-key_4_https_api.weatherbit.io_443_/v2.0/current?city_id=4487042"

一旦你有了一些智能的密鑰,我認為你很高興,最終的解決方案可能是這樣的:

<policies>
    <inbound>
        <set-variable name="cacheKey" value="@{
            return ""; // here implement some smart key generation based on the request parameters from context. 
        }" />
        <set-variable name="mustRevalidate" value="@(context.Request.Headers.GetValueOrDefault("Cache-Control","").Contains("must-revalidate"))" />
        <choose>
            <when condition="@(context.Variables.GetValueOrDefault<bool>("mustRevalidate") == true)">
                <cache-remove-value key="@(context.Variables.GetValueOrDefault<string>("cacheKey"))" />
            </when>
        </choose>
        <cache-lookup-value key="@(context.Variables.GetValueOrDefault<string>("cacheKey"))" variable-name="cachedResponse" />
        <choose>
            <when condition="@(context.Variables.GetValueOrDefault<JObject>("cachedResponse") != (JObject)null)">
                <return-response>
                    <set-header name="Content-Type" exists-action="override">
                        <value>application/json; charset=utf-8</value>
                    </set-header>
                    <set-body>@{
                        return context.Variables.GetValueOrDefault<JObject>("cachedResponse").ToString();
                    }</set-body>
                </return-response>
            </when>
        </choose>
        <base />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <cache-store-value key="@(context.Variables.GetValueOrDefault<string>("cacheKey"))" value="@(context.Response.Body.As<JObject>(preserveContent: true))" duration="30" />
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

當然,這僅緩存響應,如果您還想緩存標頭,則必須實現如何存儲它的機制,然后何時在<return-response>返回它,如何將其解析為標頭和身體。 我希望你能看到這個解決方案的缺點是什么,你需要自己實現一切。 您不能再使用<cache-lookup><cache-store>的內置功能。 但同時你有更多的自由,可以實現你想要的。 不管怎樣,祝你好運。

附注。 <cache-store-value>策略具有caching-type屬性。 您可以使用它來將緩存更改為外部緩存。

@SteppingRazor **考慮我們使用緩存類型作為內部** 您對以下問題有什么想法嗎,

  1. 如果我們想清除緩存,我們如何識別所有存儲的密鑰?
  2. 如何從內存中刪除它?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM