.NET的Google API客户端:如何实现指数补偿 [英] Google API Client for .NET: How to implement Exponential Backoff

查看:77
本文介绍了.NET的Google API客户端:如何实现指数补偿的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一种方法,可以使用.NET Core和Google的.NET客户端库将批处理请求中的成员添加到google组.代码如下:

I've created a method to add members in a Batch Request to a google group using .NET core and google's .NET client library. The code looks like this:

private void InitializeGSuiteDirectoryService()
{
    _directoryServiceCredential = GoogleCredential
        .FromJson(GlobalSettings.Instance.GSuiteSettings.Credentials)
        .CreateScoped(_scopes)
        .CreateWithUser(GlobalSettings.Instance.GSuiteSettings.User);

    _directoryService = new DirectoryService(new  BaseClientService.Initializer()
    {
        HttpClientInitializer = _directoryServiceCredential,
        ApplicationName = _applicationName
    });
}

public OperationResult<int> AddGroupMembers(Group group, IEnumerable<Member> members)
{
    var result = new OperationResult<int>();
    var memberList = members.ToList();
    var batchRequestCount = 0;

    if (memberList.Any())
    {
        var request = new BatchRequest(_directoryService);

        foreach (var member in memberList)
        {
            batchRequestCount++;
            request.Queue<Members>(_directoryService.Members.Insert(member, group.Id), (content, error, i, message) =>
            {
                if (message.IsSuccessStatusCode)
                {
                    //log OK
                }
                else
                {
                    // Implement Exponential backoff only on the request that failed.
                }
            });
            if (batchRequestCount == 30|| member.Equals(memberList.Last()))
            {
                request.ExecuteAsync().Wait();
                request = new BatchRequest(_directoryService); //Clear queue
            }
        }
    }

    return result;
}

如果成员数量很少,则逻辑工作正常;但是,当成员数为100(这是我的Google测试实例中的最大用户数量)时,我从Google收到一条错误消息:"quotaExceeded".根据Google的文档,该批处理请求的限制为他们的Admin SDK为1000,当我们达到30个限制时,我将逻辑设置为执行".

The logic works fine if the amount of members is small; however, when the members count is let's say 100( this is the max amount of users in my google's test instance), I get an Error from Google that reads: "quotaExceeded". According to Google's documentation, the limit for a batch request on their Admin SDK is 1000 and I've set my logic to Execute when we reach a limit of 30.

问题是:每当发生此错误时,如何实施错误处理以重试?他们的文档建议对包含可重试错误"的响应实施指数退避"(检查响应时看不到此错误).

The QUESTION is: How do I implement error handling to retry whenever I get this error? Their documentation suggests implementing 'Exponential Backoff' with a response that contains a 'retry-able error'(I don't see this when I inspect my response).

推荐答案

因此,这就是我在将成员添加到Gsuite组的调用中实现指数退避的最终目的.由于我使用的是dotnet核心,因此我可以使用' Polly ',这是一个弹性和瞬态故障处理库可立即提供此功能.可能需要重构,但是现在代码看起来像这样:

So here's what I ended up doing to implement Exponential Backoff on my call to add members to a Gsuite group. Since I'm using dotnet core, I was able to use 'Polly', which is a resilience and transient-fault-handling library that offers this functionality out of the box. There may be some need for refactoring, but here's what the code looks like for now:

    public OperationResult<int> AddGroupMembers(Group group, IEnumerable<Member> members)
    {
        var result = new OperationResult<int>();
        var memberList = members.ToList();
        var batchRequestCount = 0;

        if (memberList.Any())
        {
            var request = new BatchRequest(_directoryService);

            foreach (var member in memberList)
            {
                retryRequest = false; // This variable needs to be declared at the class level to guarantee the value is available to the original thread running the process.
                batchRequestCount++;
                request.Queue<Members>(_directoryService.Members.Insert(member, group.Id), (content, error, i, message) =>
                {
                    // If error code is 'quotaExceeded' retry the request ( You can add as many error codes as you'd like to retry here) 
                    if (error.Code == 403)
                    {
                        retryRequest = true;
                    }

                });

                // Execute batch request to add members in batches of 30 member max
                if (batchRequestCount == 30|| member.Equals(memberList.Last()))
                {

                    // Below is what the code to retry using polly looks like
                    var response = Policy
                        .HandleResult<HttpResponseMessage>(message => message.StatusCode == HttpStatusCode.Conflict)
                        .WaitAndRetry(new[]
                        {
                            TimeSpan.FromSeconds(1),
                            TimeSpan.FromSeconds(2),
                            TimeSpan.FromSeconds(4)
                        }, (results, timeSpan, retryCount, context) =>
                        {
                            // Log Warn saying a retry was required.
                        })
                        .Execute(() =>
                        {
                            var httpResponseMsg = new HttpResponseMessage();

                            // Execute batch request Synchronously
                            request.ExecuteAsync().Wait();
                            if (retryRequest)
                            {
                                httpResponseMsg.StatusCode = HttpStatusCode.Conflict;
                                retryRequest = false;
                            }
                            else
                            {
                                httpResponseMsg.StatusCode = HttpStatusCode.OK;
                            }

                            return httpResponseMsg;
                        });
                    if (response.IsSuccessStatusCode)
                    {
                       // Log info
                    }
                    else
                    {
                        // Log warn
                    }

                    requestCount = 0;
                    request = new BatchRequest(_directoryService);
                    batchCompletedCount++;
                }
            }
        }

        return result;
    }

这篇关于.NET的Google API客户端:如何实现指数补偿的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆