ホーム>source

サードパーティAPIにリクエストを送信し、そこからレスポンスを返すメソッドがあります。 このAPIでは1分間に50回の呼び出ししか許可されていないため、このAPIへのリクエストを調整したいと思います。

現在、私はポリーの使用を考えており、コードにラッパーのようなものを追加しています

var policy = Policy.Handle<HttpRequestException>()
                   .WaitAndRetryForever(retryAttempt => TimeSpan.FromMinutes(1));
var response = await policy.ExecuteAsync(async () => await DoApiCallAsync()
                           .ConfigureAwait(false));
return response;

しかし、おそらくこれを行うより良い方法があります。

あなたの答え
  • 解決した方法 # 1

    Polly  マイクロサービス間の再試行メカニズムのためにインフラストラクチャで使用しますが、 .WaitAndRetryForever はお勧めしません 、@ Stefanが言ったように、それは本当に危険に聞こえるからです。サードパーティのAPIが30分間のメンテナンス/ダウンタイム/無応答状態になった場合、どうなりますか?

    Polly を使用することをお勧めします  ネットワークの問題を克服するため。たとえば、サードパーティAPIのネットワークダウンタイムが発生する可能性がありますが、スロットルについては発生しません。

    スロットルについては、リクエストを保存し、一定のレートでリクエストを処理するキューベースのパターンを作成することをお勧めします。

    悲しいことに、これにはさらに2つの欠点があります。

    このキューが実際に大きくなり、プロセスが大量のメモリを消費しないようにするには、何らかのロジックを最後に実装する必要があります。

    応答を受信するために誰かが一定時間以上待機していると、ユーザーエクスペリエンスが低下する可能性があります。

    私はあなたのAPIの性質を知らないので、これは私が提案をすることができる限りです、あなたはこれがあなたに合うかどうか決定しなければなりません。幸運を!

    注意:  .waitAndRetryForever  内部通信に使用していて、サービスレベル契約を緩めたい場合は、それほど悪くはありません。 (たとえば、1つのサービスが停止したという理由だけで、インフラストラクチャ全体が低下することは望ましくありません)。

  • 解決した方法 # 2

    私はすべてをコントロールしたい(あなたが望むようにカスタマイズする)

    ワーカーをスケーリングして、複数のリクエストを並行して行うこともできます

    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);
                    }
                }
            }
        }
    }
    
    

  • 前へ java - JPAクエリ:サブクエリをグループ化条件に結合する
  • 次へ html - Safari/iOSでラジオボタンのAngular2 +(クリック)イベントが機能しない