質問

MusicBrainz WebServiceにリクエストを行うアプリを開発しています。 MusicBrainzマニュアルを読み、Webサービスに1秒あたり1秒以上リクエストを行わないか、クライアントIPがブロックされます。

この制限をサービスクライアントに透明にするために、どのアーキテクチャを提案しますか。

  • メソッド(たとえばgetAlbuns)を呼び出したいと思います。最後のリクエストの後にのみリクエスト1SECを作成する必要があります。
  • また、一度に10リクエストを呼び出したいと思うので、サービスはキューイングを処理し、Avaiable(非ブロッキング)の場合に結果を返します。

ありがとう!

役に立ちましたか?

解決

呼び出しの間に必要な遅延が必要なため、私は提案することをお勧めします java.util.Timer また java.util.concurrent.ScheduledThreadPoolExecutor. Timer 非常にシンプルで、完全に適切です これ 使用事例。ただし、追加のスケジューリング要件が後で特定された場合、単一のスケジュール要件が特定されている場合 Executor それらすべてを処理できます。どちらの場合でも、固定金利メソッドではなく、固定解雇法を使用します。

繰り返しのタスク 世論調査 リクエストオブジェクトの同時キュー。保留中の要求がある場合、タスクはそれを実行し、コールバックを介して結果を返します。サービスのクエリと呼び出しへのコールバックは、リクエストオブジェクトのメンバーです。

アプリケーションは、共有キューへの参照を保持します。リクエストをスケジュールするには、キューに追加するだけです。


明確にするために、スケジュールされたタスクが実行されたときにキューが空である場合、リクエストは行われません。単純なアプローチはタスクを終了することだけで、スケジューラは1秒後にタスクを呼び出して再度確認します。

ただし、これは、最近リクエストが処理されていなくても、タスクを開始するのに最大1秒かかる可能性があることを意味します。この不必要な遅延が耐えられない場合、あなた自身のスレッドを書くことはおそらく使用するよりも望ましい Timer また ScheduledThreadPoolExecutor. 。独自のタイミングループでは、リクエストが利用可能になるまで空のキューをブロックすることを選択した場合、スケジューリングをより詳細に制御できます。組み込みのタイマーは、以前の実行後に1秒間待つことが保証されていません 終了した;それらは通常、に関連してスケジュールします 始める タスクの時間。

この2番目のケースがあなたが念頭に置いているものである場合、あなたの run() メソッドにはループが含まれます。各反復は始まります ブロッキング リクエストが受信されるまでキューに、時間を記録します。リクエストを処理した後、時間が再度チェックされます。時差が1秒未満の場合、 寝る 残りのために。このセットアップは、1つの要求の開始と次のリクエストの間に1秒の遅延が必要であることを前提としています。 1つの要求の終了から次の要求の間に遅延が必要な場合は、時間を確認する必要はありません。 1秒間寝てください。

もう1つ注意すべきことは、サービスが1つの要求で複数のクエリを受け入れることができる可能性があることです。これにより、オーバーヘッドが減少することです。もしそうなら、ブロックしてこれを利用してください take() 最初の要素の場合、次に使用します poll(), 、おそらく非常に短いブロッキング時間(5ミリ秒ほど)で、アプリケーションがこれ以上リクエストを行っているかどうかを確認します。もしそうなら、これらはサービスへの単一のリクエストでバンドルすることができます。もしも queue aです BlockingQueue<? extends Request>, 、それは次のように見えるかもしれません:

    Collection<Request> bundle = new ArrayList<Request>();
    bundle.add(queue.take());
    while (bundle.size() < BUNDLE_MAX) {
      Request req = queue.poll(EXTRA, TimeUnit.MILLISECONDS);
      if (req == null)
        break;
      bundle.add(req);
    }
    /* Now make one service request with contents of "bundle". */

他のヒント

ローカルクライアントが呼び出すローカル「プロキシサービス」を定義する必要があります。

ローカルプロキシはリクエストを受け取り、実際のサービスに渡します。ただし、1秒あたり1つのメッセージの割合でのみ。

これをどのように行うかは、利用可能なテクノリジーに大きく依存します。

最も簡単なのは、静的および同期されたラストロクストタイムの長い時間を備えた修正されたJavaサービスです。」タイムスタンプ変数。

より洗練されたサービスでは、リクエストを受信し、単一のスレッドがリクエストをピックアップして実際のサービスに渡すというキューにそれらを配置するワーカースレッドを使用する可能性があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top