40

他のクライアントからの変更や修正を監視したい REST リソースがある場合、最善の (そして最も RESTful な) 方法は何ですか?

そうするために私が持っていた1つのアイデアは、リソースが(まだ)存在しない場合にすぐに戻るのではなく、接続を開いたままにする特定のリソースを提供することです。たとえば、次のリソースがあるとします。

/game/17/playerToMove

このリソースの「GET」は、対戦相手が動く番だと教えてくれるかもしれません。このリソースを継続的にポーリングして自分の番がいつ移動するかを確認するのではなく、移動番号 (たとえば 5) をメモして、次の移動を取得しようとする場合があります。

/game/17/move/5

「通常の」REST モデルでは、この URL に対する GET リクエストは 404 (見つかりません) エラーを返すようです。ただし、代わりに、対戦相手が彼の動きをプレイするまでサーバーが接続を開いたままにした場合、つまり:

PUT /game/17/move/5

サーバーは、対戦相手がそのリソースに PUT したコンテンツを返すことができます。これにより、必要なデータが得られるだけでなく、対戦相手がポーリングを必要とせずに移動したときの一種の通知も得られます。

この種のスキームは RESTful ですか? それとも、ある種の REST 原則に違反していますか?

4

3 に答える 3

28

提案されたソリューションは長いポーリングのように聞こえますが、これは非常にうまく機能する可能性があります。

要求する/game/17/move/5と、移動5が完了するまで、サーバーはデータを送信しません。接続が切断された場合、またはタイムアウトが発生した場合は、有効な応答が得られるまで再接続するだけです。

これの利点は、非常に高速であるということです。サーバーが新しいデータを取得するとすぐに、クライアントはそれを取得します。また、接続の切断に対しても回復力があり、クライアントがしばらく切断された場合でも機能します(クライアントが/game/17/move/5移動されてから1時間後に要求し、データを即座に取得してから、に移動するmove/6/など)。

長いポーリングの問題は、各「ポーリング」がサーバースレッドを拘束することです。これにより、Apacheなどのサーバーがすぐに破損します(ワーカースレッドが不足するため、他のリクエストを受け入れることができません)。長いポーリング要求を処理するには、専用のWebサーバーが必要です。Pythonモジュールtwisted(「イベント駆動型ネットワークエンジン」)はこれに最適ですが、通常のポーリングよりも手間がかかります。

Jetty / Tomcatについてのあなたのコメントに答えて、私はJavaの経験がありませんが、どちらもApacheと同様のworker-threadsシステムを使用しているようですので、同じ問題が発生します。私はこの問題に正確に対処しているように見えるこの投稿を見つけました(Tomcatの場合)

于 2009-01-02T04:39:44.973 に答える
2

接続を開いたままにしておくと、同じドメインへのクライアントのブラウザー要求をアクティブにブロックできるため、目的のクライアントが Web ブラウザーの場合は 404 をお勧めします。ポーリングの頻度はクライアント次第です。


2021年編集:上記の回答は、文脈上、2009年のものです。

今日は、プッシュ通知で WebSocket インターフェイスを使用することをお勧めします。

または、上記の提案では、クライアントで複数の接続を作成するオーバーヘッドを減らすために、接続を 500 ~ 1000 ミリ秒保持し、404 を返す前にサーバーで 2 回チェックすることをお勧めします。

于 2009-01-02T03:54:18.030 に答える
2

この記事では、新しい HTTP ヘッダー "When-Modified-After" を提案しているのを見つけました。これは基本的に同じことを行います。つまり、リソースが変更されるまで、サーバーは待機し、接続を開いたままにします。

私は、タイムスタンプ ベースのアプローチよりもバージョン ベースのアプローチを好みます。競合状態が発生しにくく、何を取得しているかについてもう少し情報が得られるからです。このアプローチに対する考えはありますか?

于 2009-01-02T03:43:17.147 に答える