Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 处理HTTP 429错误的最佳方法_C#_Rest_Http Status Code 429 - Fatal编程技术网

C# 处理HTTP 429错误的最佳方法

C# 处理HTTP 429错误的最佳方法,c#,rest,http-status-code-429,C#,Rest,Http Status Code 429,我正在使用一个api,如果在五分钟内点击次数超过250次,它将返回429个太多的请求和响应。计数每五分钟重置一次,所以我一直这样处理: try { return request.GetResponse(); } catch (Exception e) { if (e.Message.Contains("429")) { System.Threading.Thread.Sleep(5 * 60 * 1000); return reques

我正在使用一个api,如果在五分钟内点击次数超过250次,它将返回429个太多的请求和响应。计数每五分钟重置一次,所以我一直这样处理:

try
{
    return request.GetResponse();  
}
catch (Exception e)
{
    if (e.Message.Contains("429"))
    {
        System.Threading.Thread.Sleep(5 * 60 * 1000);
        return request.GetResponse();
    }
    else
    {
        throw new Exception(e.Message);
    }
}
    public override void DoAction()
    {
        throttle();
        var url = ContentUri;
        var request = (HttpWebRequest)WebRequest.Create(url);
        request.Method = "GET";
        request.Headers.Add("Authorization", "Bearer " + AccessToken);
        request.Accept = "application/json";
        WebResponse response = request.GetResponse();
        var dataStream = new MemoryStream();
        using (Stream responseStream = request.GetResponse().GetResponseStream())
        {
            //DO STUFF WITH THE DOWNLOADED DATA HERE...
        }
        dataStream.Close();
        response.Close();
    }

这是处理这种情况的正确方法吗?

您不应该对异常类进行字符串解析。反过来,异常类不应将重要信息放入消息字段。 您对异常的整个捕获和重新引用也是错误的。所以在前面,你们应该仔细阅读正确的异常处理。以下是我经常链接的两篇文章:

除非我上错了网络课,我想你应该去。我认为这就是从这个函数中获取HTTP错误代码的方法,但我并不是很确定


最好是完全避免例外情况。所以我不得不问:为什么你经常连续调用这个函数?是否没有合适的批量检索功能?这项服务是否打算这样自动化?

这里要考虑的一件事是,如果你开始超过限制,你正在消耗的API可能会“惩罚”你。我认为最好是主动控制api请求,这样您就不会收到429个错误

从我们正在使用的api开始,我们在应用程序上遇到了同样的问题(429个错误)。此特定api的限制为每60秒10次。我们实现了一个
throttle()
函数,该函数利用嵌入日期/时间的内存缓存。我们使用的api还跟踪了客户的使用情况。你可能不需要这个。但这是一个片段,我们用来限制我们的请求,以确保我们始终处于限制之下:

    private void throttle()
    {
        var maxPerPeriod = 250;
        //If you utilize multiple accounts, you can throttle per account. If not, don't use this:
        var keyPrefix = "a_unique_id_for_the_basis_of_throttling";
        var intervalPeriod = 300000;//5 minutes
        var sleepInterval = 5000;//period to "sleep" before trying again (if the limits have been reached)
        var recentTransactions = MemoryCache.Default.Count(x => x.Key.StartsWith(keyPrefix));
        while (recentTransactions >= maxPerPeriod)
        {
            System.Threading.Thread.Sleep(sleepInterval);
            recentTransactions = MemoryCache.Default.Count(x => x.Key.StartsWith(keyPrefix));
        }
        var key = keyPrefix + "_" + DateTime.Now.ToUniversalTime().ToString("yyyyMMddHHmm");
        var existing = MemoryCache.Default.Where(x => x.Key.StartsWith(key));
        if (existing != null && existing.Any())
        {
            var counter = 2;
            var last = existing.OrderBy(x => x.Key).Last();
            var pieces = last.Key.Split('_');
            if (pieces.Count() > 2)
            {
                var lastCount = 0;
                if (int.TryParse(pieces[2], out lastCount))
                {
                    counter = lastCount + 1;
                }
            }
            key = key + "_" + counter;
        }
        var policy = new CacheItemPolicy
        {
            AbsoluteExpiration = DateTimeOffset.UtcNow.AddMilliseconds(intervalPeriod)
        };
        MemoryCache.Default.Set(key, 1, policy);
    }
我们在代码中使用了这个
throttle()
函数,如下所示:

try
{
    return request.GetResponse();  
}
catch (Exception e)
{
    if (e.Message.Contains("429"))
    {
        System.Threading.Thread.Sleep(5 * 60 * 1000);
        return request.GetResponse();
    }
    else
    {
        throw new Exception(e.Message);
    }
}
    public override void DoAction()
    {
        throttle();
        var url = ContentUri;
        var request = (HttpWebRequest)WebRequest.Create(url);
        request.Method = "GET";
        request.Headers.Add("Authorization", "Bearer " + AccessToken);
        request.Accept = "application/json";
        WebResponse response = request.GetResponse();
        var dataStream = new MemoryStream();
        using (Stream responseStream = request.GetResponse().GetResponseStream())
        {
            //DO STUFF WITH THE DOWNLOADED DATA HERE...
        }
        dataStream.Close();
        response.Close();
    }

它基本上在缓存中跟踪您的请求。如果已达到限制,它将暂停,直到经过足够的时间,使您仍然处于限制之下。

似乎非常容易出错。你为什么这么频繁地打电话?你能通过一个请求获得更多的数据吗?这感觉就像使用异常的逻辑,这几乎从来都不是最好的选择
try..catch
对于可能是有条件的内容来说是相当沉重的。@DanielA.White,这是非常罕见的,因为它经常被这样称呼。大约每季度验证一次数据。不幸的是,在这些时间里,它需要在一天内被多次调用,而我无法控制rest服务来扩展返回的数据。事实上,该服务并不打算以这种方式使用。但是,在服务更新之前,业务规则要求我们这样做。我肯定会阅读更多关于异常处理的内容。诚然,这是我的一个薄弱环节,这也是我寻求建议的原因。谢谢然后你需要快速访问它,所以5分钟内250个电话就足够了。也许你可以在某种程度上达到极限,你可以把自己的服务缓存在客户端和原始服务器之间。实际上,在我们说话的时候,我正在建立这个过程,这更多的是一种短期内的助带方法来保持灯亮。谢谢Matt,这是在投掷错误之前暂停的好建议。我将尝试并实现类似的东西。再次感谢Matt,在我的代码中实现了类似的方法(没有特定于帐户的数据),效果非常好。基本上使用了检查呼叫计数和UTC时间戳的组合。