以程序設計方式使用 Azure Resource Graph 數據時,請務必考慮節流如何影響查詢的結果。 變更資料要求方式可協助您和貴組織避免遇到節流問題,並維持關於 Azure 資源的及時資料流量。
本文涵蓋了與在 Azure Resource Graph 中建立查詢相關的四個領域和模式:
- 了解節流標頭。
- 分組查詢。
- 錯開查詢。
- 分頁的效果。
了解節流標頭
Azure Resource Graph 會根據時間範圍,為每個使用者配置配額編號。 例如,使用者在每 5 秒的時間範圍內,最多可以傳送 15 個查詢而不會進行節流。 配額值是由許多因素所決定,而且可能會變更。
在每個查詢回應中,Azure Resource Graph 都會加入兩個節流標頭:
-
x-ms-user-quota-remaining
(int):使用者的剩餘資源配額。 此值會對應至查詢計數。 -
x-ms-user-quota-resets-after
(hh:mm:ss):使用者配額耗用量重設之前的剩餘時間長度。
當安全性主體可以存取租用戶或管理群組查詢範圍內超過 10,000 個訂閱時,回應會限制為前 10,000 個訂閱,且 x-ms-tenant-subscription-limit-hit
標頭會傳回為 true
。
為了說明標頭的作用,讓我們看一下具有標頭和值 x-ms-user-quota-remaining: 10
和 x-ms-user-quota-resets-after: 00:00:03
的查詢回應。
- 在接下來的 3 秒內,最多可以提交 10 個查詢,而不會進行節流。
- 在 3 秒內,
x-ms-user-quota-remaining
和x-ms-user-quota-resets-after
的值會分別重設為15
和00:00:05
。
若要查看在查詢要求中使用標頭進行輪詢的範例,請參閱以平行方式查詢中的範例。
群組查詢
依訂用帳戶、資源群組或個別資源來分組查詢,會比平行處理查詢更有效率。 較大查詢的配額成本通常小於許多小型和目標查詢的配額成本。 建議群組大小小於 300。
最佳化方法不佳的範例。
// NOT RECOMMENDED var header = /* your request header */ var subscriptionIds = /* A big list of subscriptionIds */ foreach (var subscriptionId in subscriptionIds) { var userQueryRequest = new QueryRequest( subscriptions: new[] { subscriptionId }, query: "Resources | project name, type"); var azureOperationResponse = await this.resourceGraphClient .ResourcesWithHttpMessagesAsync(userQueryRequest, header) .ConfigureAwait(false); // ... }
最佳化群組方法的範例。
// RECOMMENDED var header = /* your request header */ var subscriptionIds = /* A big list of subscriptionIds */ const int groupSize = 100; for (var i = 0; i <= subscriptionIds.Count / groupSize; ++i) { var currSubscriptionGroup = subscriptionIds.Skip(i * groupSize).Take(groupSize).ToList(); var userQueryRequest = new QueryRequest( subscriptions: currSubscriptionGroup, query: "Resources | project name, type"); var azureOperationResponse = await this.resourceGraphClient .ResourcesWithHttpMessagesAsync(userQueryRequest, header) .ConfigureAwait(false); // ... }
在單一查詢中取得多個資源的最佳化群組方法範例。
Resources | where id in~ ({resourceIdGroup}) | project name, type
// RECOMMENDED var header = /* your request header */ var resourceIds = /* A big list of resourceIds */ const int groupSize = 100; for (var i = 0; i <= resourceIds.Count / groupSize; ++i) { var resourceIdGroup = string.Join(",", resourceIds.Skip(i * groupSize).Take(groupSize).Select(id => string.Format("'{0}'", id))); var userQueryRequest = new QueryRequest( subscriptions: subscriptionList, query: $"Resources | where id in~ ({resourceIdGroup}) | project name, type"); var azureOperationResponse = await this.resourceGraphClient .ResourcesWithHttpMessagesAsync(userQueryRequest, header) .ConfigureAwait(false); // ... }
錯開查詢
由於強制執行節流的方式,因此建議您將查詢錯開。 例如,比起同時傳送 60 個查詢,不如將查詢錯開成四個時長 5 秒的間隔。
非交錯查詢排程。
查詢計數 六十 0 0 0 時間間隔 (秒) 0-5 5-10 10-15 15-20 交錯查詢排程。
查詢計數 15 15 15 15 時間間隔 (秒) 0-5 5-10 10-15 15-20
下列程式碼是在查詢 Azure Resource Graph 時遵循節流標頭的範例。
while (/* Need to query more? */)
{
var userQueryRequest = /* ... */
// Send post request to Azure Resource Graph
var azureOperationResponse = await this.resourceGraphClient
.ResourcesWithHttpMessagesAsync(userQueryRequest, header)
.ConfigureAwait(false);
var responseHeaders = azureOperationResponse.response.Headers;
int remainingQuota = /* read and parse x-ms-user-quota-remaining from responseHeaders */
TimeSpan resetAfter = /* read and parse x-ms-user-quota-resets-after from responseHeaders */
if (remainingQuota == 0)
{
// Need to wait until new quota is allocated
await Task.Delay(resetAfter).ConfigureAwait(false);
}
}
以平行方式查詢
雖然建議在平行處理時使用群組,但有時候查詢無法輕鬆地分組。 在這些情況下,您可能會想要以平行方式傳送多個查詢來查詢 Azure Resource Graph。 下列範例示範如何根據節流標頭「輪詢」。
IEnumerable<IEnumerable<string>> queryGroup = /* Groups of queries */
// Run groups in parallel.
await Task.WhenAll(queryGroup.Select(ExecuteQueries)).ConfigureAwait(false);
async Task ExecuteQueries(IEnumerable<string> queries)
{
foreach (var query in queries)
{
var userQueryRequest = new QueryRequest(
subscriptions: subscriptionList,
query: query);
// Send post request to Azure Resource Graph.
var azureOperationResponse = await this.resourceGraphClient
.ResourcesWithHttpMessagesAsync(userQueryRequest, header)
.ConfigureAwait(false);
var responseHeaders = azureOperationResponse.response.Headers;
int remainingQuota = /* read and parse x-ms-user-quota-remaining from responseHeaders */
TimeSpan resetAfter = /* read and parse x-ms-user-quota-resets-after from responseHeaders */
if (remainingQuota == 0)
{
// Delay by a random period to avoid bursting when the quota is reset.
var delay = (new Random()).Next(1, 5) * resetAfter;
await Task.Delay(delay).ConfigureAwait(false);
}
}
}
分頁
因為 Azure Resource Graph 在單一查詢回應中最多傳回 1,000 個項目,所以您可能需要將查詢分頁,以取得您想要的完整資料集。 但是,某些 Azure Resource Graph 的用戶端處理編頁的方式與其他用戶端不同。
使用 ResourceGraph SDK 時,您必須將先前查詢回應所傳回的跳過權杖傳遞至下一個編頁查詢,以處理編頁。 這種設計表示您需要從所有編頁呼叫中收集結果,並將其結合在一起。 在此情況下,您傳送的每個編頁查詢都會採用一個查詢配額。
var results = new List<object>();
var queryRequest = new QueryRequest(
subscriptions: new[] { mySubscriptionId },
query: "Resources | project id, name, type");
var azureOperationResponse = await this.resourceGraphClient
.ResourcesWithHttpMessagesAsync(queryRequest, header)
.ConfigureAwait(false);
while (!string.IsNullOrEmpty(azureOperationResponse.Body.SkipToken))
{
queryRequest.Options ??= new QueryRequestOptions();
queryRequest.Options.SkipToken = azureOperationResponse.Body.SkipToken;
var azureOperationResponse = await this.resourceGraphClient
.ResourcesWithHttpMessagesAsync(queryRequest, header)
.ConfigureAwait(false);
results.Add(azureOperationResponse.Body.Data.Rows);
// Inspect throttling headers in query response and delay the next call if needed.
}
ARG GET/LIST API
ARG 引進了現有 Azure 控制平面 GET 和列出 API 呼叫的替代方法,可改善延展性和效能,同時解決 Azure 客戶的節流問題。 此 API 目前僅支援resources
資料表和computeresources
資料表中的資源。
ARG GET/LIST API 旨在解決您需要依標識符查閱單一資源的案例,或是將資源列在相同類型和特定範圍內(訂用帳戶、資源群組或父資源)。
如果您的服務屬於下列類別的一或多個類別,您應該考慮ARG GET/LIST API:
您的服務會發出大量 GET 呼叫,以擷取以單一訂用帳戶或單一 RG 為目標,且不需要透過複雜篩選或聯結來自多個訂用帳戶的記錄批次的資源資料。
您的服務會發出大量的 GET 要求,而且有風險:
- 面臨節流。
- 與其他客戶競爭節流配額。
- 您的服務可能傾向於在短時間內發出大量並行的 GET 要求。
您的服務需要 GET 要求的高可用性和更快的效能,才能管理單一資源或列舉特定範圍內的資源清單。
您需要統一和 Flex 協調流程模式中 VM 和 VMSS VM 的完整 instanceView。
備註
ARG GET/LIST API 不支持實例視圖中的 VM 和 VMSS VM 健康狀態及擴充功能執行狀態。 若要深入瞭解 ARG GET/LIST API 限制,請參閱 已知的限制。
如果您感興趣的資源位於數據表或resources
數據表中computeresources
,且屬於上述其中一個類別,請使用ARG GET/LIST API
仍在進行節流?
如果您使用此文章的建議並嘗試過 Azure Resource Graph GET/LIST API 解決方案,但您的 Azure Resource Graph 查詢仍然受限,請聯絡 Azure Resource Graph 團隊。 小組支援 Azure Resource Graph,但不支援 Microsoft Graph 節流。
當您連絡 Azure Resource Graph 小組時,請提供下列詳細資料:
- 您的特定使用案例和商務驅動程式需要更高的節流限制。
- 您有多少資源可以存取? 從單一查詢傳回其中多少項目?
- 您感興趣的資源類型為何?
- 您的查詢模式是什麼? 每 Y 秒 X 個查詢,依此類推。