[英]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 **考慮我們使用緩存類型作為內部** 您對以下問題有什么想法嗎,
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.