Azure Key Vault 限制指南Azure Key Vault throttling guidance

限制进程可在启动后,用于限定对 Azure 服务发出的并发调用数,以防止过度使用资源。Throttling is a process you initiate that limits the number of concurrent calls to the Azure service to prevent overuse of resources. Azure Key Vault (AKV) 能够处理大量请求。Azure Key Vault (AKV) is designed to handle a high volume of requests. 在请求数过多的情况下,限制客户端请求可帮助 AKV 服务保持最佳性能和可靠性。If an overwhelming number of requests occurs, throttling your client's requests helps maintain optimal performance and reliability of the AKV service.

限制值因情况而异。Throttling limits vary based on the scenario. 例如,如果正在执行大量写入,则发生限制的可能性会比仅执行读取高。For example, if you are performing a large volume of writes, the possibility for throttling is higher than if you are only performing reads.

Key Vault 如何处理其限制?How does Key Vault handle its limits?

Key Vault 中的服务限制用于防止资源滥用,确保所有 Key Vault 客户端的服务质量。Service limits in Key Vault are there to prevent misuse of resources and ensure quality of service for all of Key Vault’s clients. 当超过服务阈值时,Key Vault 会在一段时间内限制该客户端发出其他任何请求。When a service threshold is exceeded, Key Vault limits any further requests from that client for a period of time. 在这种情况下,Key Vault 返回 HTTP 状态代码 429(请求过多),请求失败。When this happens, Key Vault returns HTTP status code 429 (Too many requests), and the requests fail. 此外,Key Vault 会跟踪向限制值返回 429 计数的失败请求。Also, failed requests that return a 429 count towards the throttle limits tracked by Key Vault.

如果出现限制值较高的有效业务用例,请与我们联系。If you have a valid business case for higher throttle limits, please contact us.

如何针对服务限制来限制应用How to throttle your app in response to service limits

以下是在服务受到限制时应实施的最佳做法The following are best practices you should implement when your service is throttled:

  • 减少每个请求的操作数。Reduce the number of operations per request.
  • 减少请求频率。Reduce the frequency of requests.
  • 避免立即重试。Avoid immediate retries.
    • 发出的所有请求要符合使用限制。All requests accrue against your usage limits.

实现应用的错误处理时,请使用 HTTP 错误代码 429 检测是否需要限制客户端。When you implement your app's error handling, use the HTTP error code 429 to detect the need for client-side throttling. 如果请求再次失败,错误代码为 HTTP 429,则仍会遇到 Azure 服务限制。If the request fails again with an HTTP 429 error code, you are still encountering an Azure service limit. 请继续使用推荐的客户端限制方法,重试请求直至成功。Continue to use the recommended client-side throttling method, retrying the request until it succeeds.

实现指数退避的代码如下所示。Code that implements exponential backoff is shown below.

    public sealed class RetryWithExponentialBackoff
    {
        private readonly int maxRetries, delayMilliseconds, maxDelayMilliseconds;

        public RetryWithExponentialBackoff(int maxRetries = 50,
            int delayMilliseconds = 200,
            int maxDelayMilliseconds = 2000)
        {
            this.maxRetries = maxRetries;
            this.delayMilliseconds = delayMilliseconds;
            this.maxDelayMilliseconds = maxDelayMilliseconds;
        }

        public async Task RunAsync(Func<Task> func)
        {
            ExponentialBackoff backoff = new ExponentialBackoff(this.maxRetries,
                this.delayMilliseconds,
                this.maxDelayMilliseconds);
            retry:
            try
            {
                await func();
            }
            catch (Exception ex) when (ex is TimeoutException ||
                ex is System.Net.Http.HttpRequestException)
            {
                Debug.WriteLine("Exception raised is: " +
                    ex.GetType().ToString() +
                    " –Message: " + ex.Message +
                    " -- Inner Message: " +
                    ex.InnerException.Message);
                await backoff.Delay();
                goto retry;
            }
        }
    }

    public struct ExponentialBackoff
    {
        private readonly int m_maxRetries, m_delayMilliseconds, m_maxDelayMilliseconds;
        private int m_retries, m_pow;

        public ExponentialBackoff(int maxRetries, int delayMilliseconds,
            int maxDelayMilliseconds)
        {
            m_maxRetries = maxRetries;
            m_delayMilliseconds = delayMilliseconds;
            m_maxDelayMilliseconds = maxDelayMilliseconds;
            m_retries = 0;
            m_pow = 1;
        }

        public Task Delay()
        {
            if (m_retries == m_maxRetries)
            {
                throw new TimeoutException("Max retry attempts exceeded.");
            }
            ++m_retries;
            if (m_retries < 31)
            {
                m_pow = m_pow << 1; // m_pow = Pow(2, m_retries - 1)
            }
            int delay = Math.Min(m_delayMilliseconds * (m_pow - 1) / 2,
                m_maxDelayMilliseconds);
            return Task.Delay(delay);
        }
    }

在客户端 C# 应用程序中使用此代码很简单。Using this code in a client C# application is straightforward. 下面的示例演示使用 HttpClient 类的方法。The following example shows how, using the HttpClient class.

public async Task<Cart> GetCartItems(int page)
{
    _apiClient = new HttpClient();
    //
    // Using HttpClient with Retry and Exponential Backoff
    //
    var retry = new RetryWithExponentialBackoff();
    await retry.RunAsync(async () =>
    {
        // work with HttpClient call
        dataString = await _apiClient.GetStringAsync(catalogUrl);
    });
    return JsonConvert.DeserializeObject<Cart>(dataString);
}

请记住,此代码仅适用于概念证明。Remember that this code is suitable only as a proof of concept.

出现 HTTP 错误代码 429 时,请使用指数延迟方法开始限制客户端:On HTTP error code 429, begin throttling your client using an exponential backoff approach:

  1. 等待 1 秒,然后重试请求Wait 1 second, retry request
  2. 如果仍受限制,请等待 2 秒,然后重试请求If still throttled wait 2 seconds, retry request
  3. 如果仍受限制,请等待 4 秒,然后重试请求If still throttled wait 4 seconds, retry request
  4. 如果仍受限制,请等待 8 秒,然后重试请求If still throttled wait 8 seconds, retry request
  5. 如果仍受限制,请等待 16 秒,然后重试请求If still throttled wait 16 seconds, retry request

此时,应不会收到 HTTP 429 响应代码。At this point, you should not be getting HTTP 429 response codes.