問題描述
使用Azure API Management, 想對(duì)一些固定的IP地址進(jìn)行訪問次數(shù)的限制欢策,如被限制的IP地址一分鐘可以訪問10次黄鳍,而不被限制的IP地址則可以無(wú)限訪問?
ChatGPT 解答
最近ChatGPT爆火窃款,所以也把這個(gè)問題讓ChatGPT來(lái)解答课兄,然后人工驗(yàn)證它的回答正確與否?
根據(jù)對(duì)APIM Policy的文檔參考晨继, choose 和 rate-limit 策略組合理論上的確可以實(shí)現(xiàn)要求, 接下來(lái)就讓我們實(shí)際驗(yàn)證:
- choose策略:https://docs.azure.cn/zh-cn/api-management/api-management-advanced-policies#choose 烟阐,choose 策略根據(jù)布爾表達(dá)式的求值結(jié)果應(yīng)用括住的策略語(yǔ)句,類似于編程語(yǔ)言中的 if-then-else 或開關(guān)構(gòu)造紊扬。
- rate-limit策略:https://docs.azure.cn/zh-cn/api-management/api-management-access-restriction-policies#LimitCallRate 蜒茄, rate-limit 策略可以對(duì)調(diào)用速率進(jìn)行限制,使每個(gè)指定時(shí)段的調(diào)用不超出指定的數(shù)目餐屎,避免單個(gè)訂閱的 API 使用量暴增檀葛。 超過(guò)調(diào)用速率時(shí),調(diào)用方會(huì)收到 429 Too Many Requests 響應(yīng)狀態(tài)代碼腹缩。
驗(yàn)證步驟
1)在API的Inbound 策略中添加 choose策略
(策略具體內(nèi)容屿聋,見文末)
-
測(cè)試驗(yàn)證,連續(xù)對(duì)該API訪問10次以上藏鹊,得到429 Too Many Requests錯(cuò)誤
image.png
3)以上證明润讥,ChatGPT針對(duì)這個(gè)問題的解答是正確的!
工程師解答
在參考ChatGPT給出的 choose + rate limit 組合后盘寡,我們也發(fā)現(xiàn)另一個(gè)選項(xiàng)楚殿。使用 rate-limit-by-key 策略實(shí)現(xiàn)對(duì)特定IP的速率限制。
-
rate-limit-by-key 策略:https://docs.azure.cn/zh-cn/api-management/api-management-access-restriction-policies#LimitCallRateByKey 竿痰, 可以對(duì)調(diào)用速率進(jìn)行限制脆粥,使指定時(shí)段的調(diào)用不超出指定的數(shù)目,避免單個(gè)密鑰的 API 使用量暴增影涉。 密鑰的值可以是任意字符串冠绢,通常使用策略表達(dá)式來(lái)提供密鑰。 可以添加可選增量條件常潮,指定在決定是否到達(dá)限制值時(shí)應(yīng)該進(jìn)行計(jì)數(shù)的請(qǐng)求弟胀。 超過(guò)此調(diào)用速率時(shí),調(diào)用方會(huì)收到
429 Too Many Requests
響應(yīng)狀態(tài)代碼。
在官方文檔中給出的示例中孵户,是針對(duì)所有的IP(context.Request.IpAddress)都進(jìn)行了10次/60秒****請(qǐng)求的限制萧朝,而本示例中則特指“某些固定IP”限制。那么如何來(lái)完成這個(gè)需求呢夏哭?
答案 就在“rate-limit-by-key 策略”的說(shuō)明中检柬,”可以添加可選增量條件,指定在決定是否到達(dá)限制值時(shí)應(yīng)該進(jìn)行計(jì)數(shù)的請(qǐng)求”, 所以竖配,只要可選增量條件(increment-condition) 的值根據(jù)輸入的IP地址動(dòng)態(tài)賦值True/False何址, 就能完美匹配以上要求。
理論推斷进胯,只需要實(shí)現(xiàn)如下邏輯用爪,即可以實(shí)現(xiàn)終極需求“想對(duì)一些固定的IP地址進(jìn)行訪問次數(shù)的限制,如被限制的IP地址一分鐘可以訪問10次胁镐,而不被限制的IP地址則可以無(wú)限訪問偎血?”
只需兩步:
1)通過(guò)設(shè)置一個(gè)變量(set-variable) 值,用C#代碼來(lái)計(jì)算變量值盯漂,在賦值語(yǔ)句中颇玷,預(yù)先定義一個(gè)IP限制列表,通過(guò) contains 檢查當(dāng)前請(qǐng)求IP是否在列表中就缆,返回True or False 帖渠。True表示當(dāng)前請(qǐng)求的IP需要速率限制, 否則,不需要竭宰。
2) 然后空郊,在rate-limit-by-key 的 increment-condition條件中使用上一步參數(shù)值,進(jìn)行判斷是否計(jì)入限制
驗(yàn)證步驟
1)在API的 Inbound 策略中添加 rate-limit-by-key策略
(策略具體內(nèi)容羞延,見文末)
2)驗(yàn)證在30秒,訪問5次以上后脾还,同樣得到429 Too Many Requests錯(cuò)誤
-
當(dāng)在請(qǐng)求Headers中添加Ocp-Apim-Trace: true 和 Ocp-Apim-Subscription-Key: {訂閱Key}后伴箩,可以查看請(qǐng)求在APIM中執(zhí)行的日志跟蹤”陕可以查看rate-limit-by-key 策略的執(zhí)行情況.
image.png
總結(jié)
想實(shí)現(xiàn)固定IP地址訪問次數(shù)的限制嗤谚,至少有如下兩種解決方案。
方案一:Choose + rate-limit 策略組合
<!-- IMPORTANT:
- Policy elements can appear only within the <inbound>, <outbound>, <backend> section elements.
- To apply a policy to the incoming request (before it is forwarded to the backend service), place a corresponding policy element within the <inbound> section element.
- To apply a policy to the outgoing response (before it is sent back to the caller), place a corresponding policy element within the <outbound> section element.
- To add a policy, place the cursor at the desired insertion point and select a policy from the sidebar.
- To remove a policy, delete the corresponding policy statement from the policy document.
- Position the <base> element within a section element to inherit all policies from the corresponding section element in the enclosing scope.
- Remove the <base> element to prevent inheriting policies from the corresponding section element in the enclosing scope.
- Policies are applied in the order of their appearance, from the top down.
- Comments within policy elements are not supported and may disappear. Place your comments between policy elements or at a higher level scope. -->
<policies>
<inbound>
<base />
<set-variable name="IsCountIpLimit" value="@{
string ipAddress =context.Request.IpAddress;
List<string> cidrList = new List<string>(){
"167.xxx. xxx.135",
"167.xxx. xxx.136",
"167.xxx. xxx.137"
};
return cidrList.Contains(ipAddress);
}" />
<choose>
<when condition="@((bool)context.Variables["IsCountIpLimit"])">
<rate-limit calls="10" renewal-period="60" />
</when>
</choose>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
方案二:rate-limit-by-key策略
<!-- IMPORTANT:
- Policy elements can appear only within the <inbound>, <outbound>, <backend> section elements.
- To apply a policy to the incoming request (before it is forwarded to the backend service), place a corresponding policy element within the <inbound> section element.
- To apply a policy to the outgoing response (before it is sent back to the caller), place a corresponding policy element within the <outbound> section element.
- To add a policy, place the cursor at the desired insertion point and select a policy from the sidebar.
- To remove a policy, delete the corresponding policy statement from the policy document.
- Position the <base> element within a section element to inherit all policies from the corresponding section element in the enclosing scope.
- Remove the <base> element to prevent inheriting policies from the corresponding section element in the enclosing scope.
- Policies are applied in the order of their appearance, from the top down.
- Comments within policy elements are not supported and may disappear. Place your comments between policy elements or at a higher level scope. -->
<policies>
<inbound>
<base />
<set-variable name="IsCountIpLimit" value="@{
string ipAddress =context.Request.IpAddress;
List<string> limitIPs = new List<string>(){
"167.xxx. xxx.135",
"167.xxx. xxx.136",
"167.xxx. xxx.137"
};
return limitIPs.Contains(ipAddress);
}" />
<rate-limit-by-key calls="5" renewal-period="30" counter-key="@(context.Request.IpAddress)" increment-condition="@(context.Response.StatusCode >= 200 && context.Response.StatusCode < 300 && (bool)context.Variables["IsCountIpLimit"])" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
參考資料
choose策略:https://docs.azure.cn/zh-cn/api-management/api-management-advanced-policies#choose
rate-limit策略:https://docs.azure.cn/zh-cn/api-management/api-management-access-restriction-policies#LimitCallRate 怔蚌,
rate-limit-by-key 策略:https://docs.azure.cn/zh-cn/api-management/api-management-access-restriction-policies#LimitCallRateByKey
當(dāng)在復(fù)雜的環(huán)境中面臨問題巩步,格物之道需:濁而靜之徐清,安以動(dòng)之徐生桦踊。 云中椅野,恰是如此!
分類: 【Azure API 管理】
標(biāo)簽: rate-limit-by-key , Azure API 管理 , 429 Too Many Requests , 實(shí)現(xiàn)對(duì)部分固定IP進(jìn)行訪問次數(shù) , Choose + rate limit