为了账号安全,请及时绑定邮箱和手机立即绑定

C#中的油门方法

C#中的油门方法

C#
Helenr 2021-12-05 14:56:58
我有向某些 3rd 方 API 发出请求并从中返回响应的方法。由于此 API 每 1 分钟仅允许 50 次调用,因此我想限制对此 API 的请求。目前我正在考虑使用 Polly 并在我的代码中添加诸如包装器之类的东西var policy = Policy.Handle<HttpRequestException>()                   .WaitAndRetryForever(retryAttempt => TimeSpan.FromMinutes(1));var response = await policy.ExecuteAsync(async () => await DoApiCallAsync()                           .ConfigureAwait(false));return response;但也许这里有更好的方法来做到这一点。
查看完整描述

2 回答

?
holdtom

TA贡献1805条经验 获得超10个赞

Polly很好,我们在我们的基础设施中使用它在我们的微服务之间进行重试机制,但是我不推荐.WaitAndRetryForever,因为它听起来真的很危险,就像@Stefan 说的那样。如果第 3 方 API 在 30 分钟内进行维护/停机/无响应会发生什么我知道它不会经常发生,但仍然发生。

我会建议使用Polly来克服网络问题。例如,第 3 方 API 可能的网络停机时间,但与节流无关。

关于节流,我建议创建一些基于队列的模式,您可以在其中存储请求并以给定的速率处理它们。

可悲的是,这还有两个缺点:

  1. 您将需要在您的一端实现一些逻辑,以便此队列不会变得非常大并使您的进程消耗大量内存。

  2. 如果有人等待超过一定时间才能收到他们的回复,这可能是糟糕的用户体验。

由于我不知道您的 API 的性质,因此就我所能提供的建议而言,您必须决定这是否适合您。祝你好运!

注意: .waitAndRetryForever如果您将其用于内部通信并且想要放松服务级别协议,那还不错。(例如,您不希望您的整个基础架构仅仅因为一项服务死亡而崩溃)。


查看完整回答
反对 回复 2021-12-05
?
慕标琳琳

TA贡献1830条经验 获得超9个赞

我更喜欢控制一切(根据需要自定义)


您还可以扩展工作人员以并行发出多个请求


例子


Worker worker = new Worker();

worker.OnRetry += (id) =>

{

  //called when error occurs

  //here you can wait as you want and send next request

};

worker.OnRespnse += (sender, success) =>

{

  //called on response

  //customize success depend on response status-code/body

  //here you can wait as you want and send next request

};

worker.Start("request body");

//you can start this worker over and over

工人阶级


using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.IO;

using System.Linq;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Threading;

using System.Threading.Tasks;


namespace app

{

    class Worker

    {


        public delegate void OnRetryDelegate(int id);


        public event OnRetryDelegate OnRetry;


        public delegate void OnRespnseDelegate(Worker sender, bool success);


        public event OnRespnseDelegate OnRespnse;


        public Worker()

        {

            Id = IdProvider.GetNewId();

            thread = new Thread(new ThreadStart(ExecuteAsync));

            thread.Start();

        }


        private readonly Thread thread;

        public string Number;

        public bool Idle { get; set; }

        public bool ShutDown { get; set; }

        public bool Started { get; set; }

        public int Id { get; private set; }

        public PostData { get; set; }


        public void Start(string postData)

        {

            PostData = postData;

            Idle = true;

            Started = true;

        }


        private void ExecuteAsync()

        {

            while (!ShutDown)

            {

                Thread.Sleep(1500);

                if (Idle)

                {

                    Idle = false;

                    if (Number == "terminate")

                    {

                        ShutDown = true;

                        return;

                    }


                    try

                    {

                        var request = (HttpWebRequest) WebRequest.Create("https://example.com");

                        var data = Encoding.ASCII.GetBytes(postData);

                        Debug.Print("send:  " + postData);

                        request.Method = "POST";

                        request.ContentType = "application/x-www-form-urlencoded";

                        request.ContentLength = data.Length;

                        using (var stream = request.GetRequestStream())

                        {

                            stream.Write(data, 0, data.Length);

                        }

                        var response = (HttpWebResponse) request.GetResponse();

                        var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();

                        Debug.Print(responseString);

                        if (responseString.Contains("something"))

                            OnRespnse?.Invoke(this, true);

                    }

                    catch (Exception)

                    {

                        OnRetry?.Invoke(Id);

                    }


                    OnRespnse?.Invoke(this, false);

                }

            }

        }

    }

}



查看完整回答
反对 回复 2021-12-05
  • 2 回答
  • 0 关注
  • 220 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信