web-dev-qa-db-ja.com

多数の小さなリクエストと少数の大きなリクエスト(API設計)

私は現在、次のような組織でプロジェクトに取り組んでいます。

  • クライアント-REST api。
  • Server-サードパーティのAPIを介して他のさまざまなサーバーからデータをリクエストします
  • サードパーティAPI-サーバーにデータを提供する自分の制御不能なサービス(Reddit、Hackernews、Quoraなど)

議論のために、クライアントが最初に各サードパーティAPIからのアイテムのリストを必要としているとしましょう。このリストからアイテムが選択されます。この時点で、クライアントはアイテムの完全なコンテンツとアイテムへの応答(コメント)を確認する必要があります。私は3つのオプションの間で決定しようとしています:

アラカルト

このアプローチでは、サーバー上に3つの個別のエンドポイントがあります。1つはアイテムのリストを取得するため、1つはアイテムのメインコンテンツを取得するため、もう1つはアイテムの応答を取得するためです。

  • 長所:必要以上のリクエストを行うことはありません。リクエストは小さいので、一般的には速くなります。
  • 短所:私は多くの要求をしなければなりません。リストから項目を選択した後、ユーザーはメインコンテンツが表示されるまで待機し、その後応答を表示するまでさらに待機する必要がある場合があります。

サーバー側キャッシュ

このリクエストでは、サーバーを1回呼び出して、すべてのソースのすべてのデータを「フェッチ」します。その後、データはサーバーにキャッシュされます。その後、クライアントは前と同じRESTエンドポイントを持ちます。ただし、サーバーには既にデータがあり、それをクライアントにフィードする必要があるだけなので、呼び出し間でそれほど待機する必要はありません。

  • 長所:クライアント側での実装はまだ簡単ですが、待ち時間の問題はありません
  • 短所:もう少し複雑なサーバー側で、最初の呼び出しには本当に長い時間がかかる可能性があります。

クライアント側のキャッシュ

このシナリオは前のシナリオと似ていますが、クライアントがサーバーに要求するのは1回だけです。つまり、すべてのデータを取得します。ここから、データを保存して適切に使用するのはクライアントの責任です。

  • 長所:簡単なサーバー実装、最初の呼び出し後の非常に高速
  • 短所:最初の呼び出しは非常に遅く、より複雑なクライアント側の実装になります

どちらが最善のアプローチかわからない、またはおそらく私が明白な解決策を欠いている場合は。何かアドバイスをいただければ幸いです!

57
williamg

クライアントとサーバーの間の予想されるネットワーク遅延(ping時間など)を覚えておく必要があります。帯域幅が良好で待ち時間が長い状況では、多くの小さなリクエストが実行されます大幅に 1つの大きなリクエストよりも悪い。

私は最近、チームの1つがインドにある(残りは米国にある)マルチチームのデータベース支援Webアプリケーションプロジェクトで共同作業をしています。米国のオフィスでホストされている単一のデータベースインスタンスがあり、開発者はこのデータベースインスタンスにローカルウェブサーバーインスタンスを接続します。私のデスクはおそらくデータベースインスタンスから50フィート、2 LANホップ離れており、パフォーマンスは良好です。

インドの開発者と最初に物事を始めたとき、彼らはアプリケーションを起動してページ間を移動するのに膨大な待ち時間を経験していました。ここでは10分の待機時間について話します。これは、デスクから開発データベースサーバーへの200ミリ秒のping時間に、データベースへの多くの短いクエリが掛け合わされていたことが原因であることがわかりました。私のローカルの0.5ミリ秒のpingは取るに足らないものだったので、Webサーバーとデータベースサーバーの間のチャットは重要ではありませんでした。 Webサーバーとデータベースサーバーを地理的に分離したのはこれが初めてでした。

今回のケースでの解決策は、データベースサーバーのクローンを作成し、そのコピーをインドで立ち上げることでしたが、ここでのポイントは、クライアントとサーバーが離れている場合、ネットワークの待ち時間は、ワイヤー。接続が確立された後の帯域幅は、通常、それほど心配する必要はありません。

32
JakeRobb

これらの3つのオプションは相互に排他的ではなく、クライアント側とサーバー側の両方のキャッシュを組み合わせて使用​​できます。ただし、コメントなどの一部のデータは、キャッシュに長時間保持していると古くなる可能性があります。どうか確認できないことを考えると、たぶんそれを保存することは控えるべきです。一方、コンテンツは通常大幅に変更されることはないため、サーバー側でコンテンツをキャッシュし、クライアント側でコンテンツの一部をプリフェッチしてレイテンシを短縮しても害はありません。

2
wfdctrl

あなたが与えた情報に基づいて、オプション1、

  • 単一のクライアントリクエストでは、リンゴとオレンジを混ぜ合わせ、フルーツバスケットが非常に大きくなる可能性があります。

  • キャッシングはパフォーマンスを向上させるトレードオフですが、潜在的に一貫性が失われます(古いデータ)です。パフォーマンスの問題が特定されていない場合、同期の問題は通常リスクを伴うものではありません。

1
guillaume31

私は常にいくつかの大きなリクエストがより良いパフォーマンスとよりスケーラブルであることを発見しました。ただし、すべてのアプローチにはトレードオフがあるため、サーバーとクライアントのニーズによって異なります。別のオプションを使用することもできます。つまり、取得するデータの範囲全体またはセットをクライアントに指定させる必要があります。必ずしもすべてのデータではなく、使用可能な帯域幅に一致するように調整された範囲の一部です。

0
Frank Hileman

私は(ほぼ)割引オプション3を選びます。1と2のどちらを選択するかは、次の2つの要素によって決まります。

  • (A)単一の合計フェッチの結果の大きさ
  • (B)クライアント/ユーザーがそのセッションで通常使用する結果の詳細の詳細。

AとBが極端であるかどうかを判断するのは簡単です。

  • Aが大きくBが小さい場合は、必ずオプション1(アラカルト)を選択してください。
  • Aが小さく、Bが大きい場合は、2(サーバー側キャッシュ)または3(クライアント側キャッシュ)を使用します。

その他のA/B(大/小)バリエーションについては、裁量を適用する必要があります。私はしばしば、さまざまなクライアントからのさまざまなユースケースに対応するために、両方粗いおよび細かいエンドポイントを提供します。

0
Cornel Masson

プログラミングの常として、それは依存します。

それで、本当の質問は:A/B/Cまたは3つの組み合わせを決定するとき、あなたは何を考慮すべきですか?

実際の差別化要因は、使用しているサードパーティAPIの実装の詳細だと思います。例として、次のことを考慮してください。データは頻繁に予期せず変更されますか?彼らは「おしゃべり」または残りですか?

データが頻繁に変更されてサーバー側のキャッシュが古くなったキャッシュの問題を引き起こすほど高速で呼び出しが容易なサービスの場合は、必ずオプション1:リクエストを増やす、キャッシュなし、必要な場合のみにしてください。

外部データが予測可能な方法で変更される場合、または使用法が限られている場合、または単にサーバー上でデータをキャッシュすることでユーザーエクスペリエンスを向上させることができる場合は、2に進んでください。ただし、キャッシュは無料ではないことに注意してください。デバッグにはコストがかかり、更新が表示されないというユーザーからの不満も時々あります。

オプション3、私はデータが多くない場合にのみ検討しますが、その場合、オプション1または2でも機能し、サーバーでより多くのロジックを維持できるため、1または2を使い続けます。

ちょうど私の2c。

0
A. Chiesa