web-dev-qa-db-ja.com

APIを使用する場合、リクエストの制限に対処するための良い方法は何ですか?

私のアプリはサードパーティのAPIを使用しています。このAPIの要件の1つは、アプリが1秒あたり20を超えるリクエストを送信できないことです。このアプリの性質のため、そして私のユーザーベースが成長しているため、私たちは今、非常に頻繁にその制限に達しています。

(私のアプリについて1つ注意する必要があります:独立して実行されている4つの個別のバックグラウンドプロセスで構成されており、これらの4つのプロセスのそれぞれは、さまざまな条件に基づいて、さまざまなタイミングでサードパーティのAPIにヒットします)

レート制限を回避するための2つの可能な解決策を考え出しましたが、どちらの解決策にも欠陥があるようです。

  1. サードパーティのAPIへのすべての送信リクエストを追跡するグローバルキャッシュ(おそらくredis)を実装します。各プロセスがリクエストを試行するたびに、まずキャッシュをチェックします。過去1秒間に20未満の場合は、続行します。しかし、そうでない場合は、指定された時間待ってから、もう一度確認してください。

  2. グローバルキャッシュ、キュー、およびこのサードパーティAPIへのWebリクエストの処理専用の5番目のプロセスを実装します。私の4つのプロセスはそれぞれ、リクエストを(リクエストを直接送信する代わりに)キューに入れます。 5番目のプロセスは、キューをチェックし、条件(過去20秒間で20件未満のリクエスト)をチェックして、Webリクエストを作成し、結果をキューに戻します(それぞれ1つずつ処理されます)。一方、他のプロセス(元の要求をキューに入れたプロセス)は、キューをポーリングして応答を確認します。そして、応答があると、それを取得して(キューから項目を削除し)、陽気な方法で進みます。

#1の私の問題は正確さです。 4つのプロセスすべてが同時にキャッシュをチェックし、現在のカウントが19であると考えられます。4つのプロセスすべてが青信号を取得してリクエストを同時に送信し、カウントを最大23にすると、制限を超えたためにアプリがロックアウトされます。 。

#2の問題は複雑さです。 5番目のプロセスではすべてのリクエストが一度に1つずつ処理されるため、競合状態が原因で制限を超える可能性がないため、精度は維持されると思います。しかし、それは単に壊れやすく、おそらくやり過ぎのようです。私は多くの可動部品を導入しています。つまり、(私の経験では)多くの問題が発生する可能性があり、エラーの追跡が困難になる可能性があります。

この問題の他の解決策はありますか?私はそれを考えすぎていますか? #1または#2はうまく機能しますか?

2
Matt Spinks

制限を超えるリクエストのみを拒否し、サービス全体を強制終了するだけではなくサービスが機能する場合は、TCPの機能と同様のアルゴリズムを実装できます。

簡単に言えば、各クライアントはできるだけ早くリクエストの送信を開始します。リクエストが拒否され始めると、リクエストが拒否されない程度に遅くなります。次に、ランダムな間隔でレートを上げようとし、それ自体でレートを上げることが可能かどうかを調べます。

もちろん、これはそれ以上のリクエストを行うことを可能にすることはできませんが、各クライアントがパイを少し食べることを可能にします。

また、さまざまなクライアントが同様のリクエストを行うことが予想される場合は、何らかの形のグローバルキャッシングによって状況が確実に改善されます。

2
Euphoric

私はまた、主にこのアプローチがAPIにアクセスする「サービス」が分離されていることを意味するという事実のために、述べられているようにあなたの2番目のオプションを考え出して使用しました。これにより、APIインターフェイスが変更された場合に単一の変更点を持つなど、多くの利点が得られます。必要に応じて、実際の作業を開始する前に、API情報を他のプロセスに引き渡す前に、より望ましい形式に処理できます。以前に述べたように、より簡単な調整に加えてキャッシュメカニズム。

追加のボーナスとして、これにより、他のAPIを処理するときに並べ替えのフレームワークを使用でき、必要に応じて他のプロジェクトでAPIをより簡単に使用できます。

1
TurtleKwitty