9

リクエストを複数のマシンにマップするロード バランサーを備えた Web サービスがあります。これらの各リクエストは、外部 API に http 呼び出しを送信することになります。そのため、外部 API に送信するリクエストの数をレート制限したいと考えています。

私の現在のデザイン:

  • サービスには、受信したすべてのリクエストを格納するメモリ内のキューがあります
  • キューからリクエストを取得して処理できる頻度を制限します。

複数のマシンを使用している場合、これは機能しません。各マシンには独自のキューとレート リミッターがあるためです。たとえば、レート リミッターを 10,000 リクエスト/日に設定し、10 台のマシンを使用すると、各マシンが 10,000 リクエスト/日を処理するため、全負荷で 100,000 リクエスト/日を処理することになります。1 日に 10,000 件のリクエストのみが処理されるようにレート制限を行い、それらの 10,000 件のリクエストの負荷を分散したいと考えています。

Java と MYSQL を使用しています。

4

4 に答える 4

2
  1. memcached または redis を使用して、クライアントごとに API リクエスト カウンターを保持します。レート制限を超えている場合は、すべてのリクエストを確認してください。
  2. リクエストごとにチェックするのはコストがかかりすぎると思われる場合は、ストームを試してリクエスト ログを処理し、非同期でリクエスト カウンターを計算することができます。
于 2014-03-28T03:04:48.167 に答える
0

データベースに単純なカウンターを実装し、API クライアントにスロットリングを実装させてみませんか?

ユーザー エージェント -> LB -> サービス -> Q -> Q コンシューマー -> API クライアント-> 外部 API

API クライアントは (今日の) 数をチェックし、好きなレート制限アルゴリズムを実装できます。たとえば、数が 10k を超える場合、クライアントは単に爆発し、例外によってメッセージをキューに戻し、今日が明日になり、キューに入れられたすべての要求が処理されるまで処理を続行できます。

あるいは、階層化されたスロットリング システムを実装することもできます。たとえば、8k までフラットアウトし、ノードごとに 5 秒ごとに 1 つのメッセージを送信し、制限に達するまでその時点で 503 エラーをユーザー エージェントに送り返すことができます。

それ以外の場合は、複雑なルートに進んで分散キュー (AMQP サーバーなど) を実装することもできますが、これは問題を完全に解決しない可能性があります。 . たとえば、最大制限が 10k であるため、8 秒ごとに 1 メッセージよりも速くなることはありません。

于 2014-03-28T00:26:55.810 に答える
0

ライブラリ/サービスの使用に反対でない場合は、 https://github.com/jdwyah/ratelimit-javaを使用して、分散レート制限を簡単に取得できます。

パフォーマンスが最も重要な場合は、リクエストで複数のトークンを取得できるため、リミッターに対して API リクエストを 10 万回行う必要はありません。その詳細については、https://www.ratelim.it/documentation/batchesを参照してください。

于 2017-02-20T03:24:06.340 に答える
0

おっしゃっていたのは以下の2点です。

1)"I would like to rate limit so that only 10,000 requests get processed/day"
2)"while still load balancing those 10,000 requests."

まず、エンド ユーザーからの各要求が n 台のマシンの 1 つにマップされる分割統治アプローチを使用しているようです。したがって、指定された期間内に 10,000 件のリクエストのみが処理されるようにするには、次の 2 つのオプションがあります。

1) すべての n 台のマシンからの結果
を、外部 API がアクセスできる別のエンドポイントにルーティングするコンバイナーを実装します。このエンドポイントは、処理中のジョブの数を数えることができ、しきい値を超えている場合はジョブを拒否します。

2) もう 1 つの方法は、1 日に処理したジョブの量を変数としてデータベース内に保存することです。次に、ジョブの最初の要求時にデータベースの値がしきい値に達しているかどうかを確認するのが一般的です (マシンの 1 つに渡す前に)。しきい値に達した場合は、最初からジョブを拒否します。これは、適切なメッセージと相まって、エンド ユーザーのエクスペリエンスが向上するという利点があります。

これら 10,000 のリクエストすべてが引き続き負荷分散され、1 つの CPU が他のどの CPU よりも多くのジョブを処理しないようにするには、単純なラウンド ロビン アプローチを使用して m 個の CPU にジョブを分散する必要があります。ラウンド ロビンを使用すると、ビン/カテゴリ化アプローチと対比して、ジョブ リクエストが n 個の CPU にできるだけ均一に分散されるようになります。ラウンド ロビンの欠点は、処理しているジョブの種類によっては、スケールアップを開始するときに大量のデータを複製する可能性があることです。これが懸念される場合は、ローカリティ センシティブ ハッシュ (LSH) 関数の形式を実装することを検討する必要があります。優れたハッシュ関数はデータを可能な限り均等に分散しますが、LSH では CPU が他の CPU よりも多くのジョブを処理することになります。■ ハッシュ対象として選択した属性のスキューが発生する可能性が高い場合。いつものように、両方に関連するトレードオフがあるため、ユース ケースに最も適していることがわかります。

于 2014-03-28T01:39:06.133 に答える