RESTリソースの変更を監視するRESTfulな方法は何ですか?
-
03-07-2019 - |
質問
他のクライアントからの変更または変更を監視するRESTリソースがある場合、それを行うための最良の(そして最もRESTfulな)方法は何ですか?
そのために考えていた1つのアイデアは、リソースが(まだ)存在しない場合にすぐに戻るのではなく、接続を開いたままにする特定のリソースを提供することです。たとえば、次のリソースがある場合:
/game/17/playerToMove
a" GET"このリソースで、対戦相手が移動する番だと言うかもしれません。このリソースを継続的にポーリングして移動するタイミングを調べるのではなく、移動番号(5など)を書き留めて、次の移動を取得しようとする場合があります。
/game/17/move/5
"通常" RESTモデル、このURLに対するGETリクエストは404(not found)エラーを返すようです。ただし、代わりに、対戦相手が動きをするまでサーバーが接続を開いたままにした場合、つまり:
PUT /game/17/move/5
サーバーは、相手がそのリソースにPUTしたコンテンツを返すことができます。これにより、必要なデータと、ポーリングを必要とせずに対戦相手が移動した場合の通知が提供されます。
この種のスキームはRESTfulですか?それとも、ある種のREST原則に違反していますか?
解決
提案されたソリューションは、ロングポーリングのように聞こえますが、これは非常にうまく機能します。
/ game / 17 / move / 5
を要求すると、移動5が完了するまでサーバーはデータを送信しません。接続が切断されたり、タイムアウトが発生した場合は、有効な応答が返されるまで再接続するだけです。
この利点は非常に迅速である-サーバーが新しいデータを取得するとすぐに、クライアントがそれを取得することです。また、ドロップされた接続に対して回復力があり、クライアントがしばらく切断された場合に機能します(移動してから1時間後に / game / 17 / move / 5
を要求し、すぐにデータを取得してから移動することもできます) move / 6 /
などへ)
長いポーリングの問題は、それぞれ「ポーリング」です。サーバースレッドを結び付けます。これにより、Apacheなどのサーバーがすぐに破損します(ワーカースレッドが不足するため、他の要求を受け入れることができません)。ロングポーリングリクエストを処理するには、専用のWebサーバーが必要です。Pythonモジュール twisted
(「イベント駆動型ネットワークエンジン」)はこれに最適ですが、通常のポーリングよりも多くの作業が必要です。
Jetty / Tomcatについてのあなたのコメントに答えて、私はJavaの経験はありませんが、Apacheと同様のワーカースレッドシステムを使用しているようで、同じ問題が発生します。 この投稿が見つかりましたこの問題に正確に対処します(Tomcatの場合)
他のヒント
が見つかりましたこの記事では、基本的に同じことを行う新しいHTTPヘッダー「When-Modified-After」を提案しています。サーバーはリソースが変更されるまで待機し、接続を開いたままにします。
タイムスタンプベースのアプローチよりもバージョンベースのアプローチの方が好みです。競合状態が発生しにくく、取得しているものについてもう少し情報が得られるためです。このアプローチについて何か考えはありますか?
接続を開いたままにすると、同じドメインへのクライアントでのブラウザリクエストがアクティブにブロックされる可能性があるため、目的のクライアントがWebブラウザの場合、404をお勧めします。ポーリングの頻度はクライアント次第です。