web-dev-qa-db-ja.com

REST apiで双方向同期をどのように表すのが最善ですか?

リソースを持つWebアプリケーションがあり、別の同様のリソースを持つリモートアプリケーションへの参照があるシステムを想定して、「ローカル」リソースを「リモート」リソースと同期する双方向同期アクションをどのように表現しますか?

例:

ToDoリストを表すAPIがあります。

GET/POST/PUT/DELETE/todos /など.

そのAPIはリモートTODOサービスを参照できます。

GET/POST/PUT/DELETE/todo_services /など.

経由でプロキシとして私のAPIを介してリモートサービスからToDoを操作できます

GET/POST/PUT/DELETE/todo_services/abc123 /など.

ローカルのTODOセットとリモートのTODOSセットの間で双方向同期を実行する機能が必要です。

RPCのような方法で、

POST/todo_services/abc123/sync /

しかし、「動詞は悪い」という考えで、この行動を表すより良い方法はありますか?

25
Edward M Smith

リソースはどこにありますか?

RESTはすべて、ステートレスで発見可能な方法でリソースに対処することを目的としています。ハイパーメディアデータ形式を使用することを強くお勧めしますが、HTTP経由で実装する必要はなく、JSONやXMLに依存する必要もありません( [〜#〜] hateoas [〜#〜 ] 原則)リンクとIDが望ましいため。

したがって、問題は次のようになります。リソースの観点から同期についてどう思いますか?

双方向同期とは何ですか?**

双方向同期は、ノードのグラフに存在するリソースを更新するプロセスであり、プロセスの最後に、すべてのノードがそれらのリソースを管理するルールに従ってリソースを更新します。通常、これは、すべてのノードがグラフ内に存在する最新バージョンのリソースを持つことになると理解されています。最も単純な場合、グラフはローカルとリモートの2つのノードで構成されます。ローカルが同期を開始します。

したがって、対処する必要のある重要なリソースはトランザクションログです。したがって、同期プロセスは、HTTPの「items」コレクションでは次のようになります。

手順1-ローカルがトランザクションログを取得する

ローカル:GET /remotehost/items/transactions?earliest=2000-01-01T12:34:56.789Z

Remote:200 OKこれに類似したフィールドを含むトランザクションログを含む本文.

  • itemId-共有主キーを提供するUUID

  • updatedAt-データが最後に更新されたときの調整ポイントを提供するためのタイムスタンプ(改訂履歴が不要であると想定)

  • fingerprint-updateAtが数秒経過した場合の迅速な比較のためのデータの内容のSHA1ハッシュ

  • itemURI-後で取得できるようにするアイテムの完全なURI

手順2-ローカルがリモートトランザクションログを自身のログと比較する

これは同期方法のビジネスルールのアプリケーションです。通常、itemIdはローカルリソースを識別し、フィンガープリントを比較します。違いがある場合は、updatedAtの比較が行われます。これらが呼び出しに近すぎる場合は、他のノードに基づいてプルする(おそらくそれがより重要である)か、他のノードにプッシュする(このノードがより重要)かを決定する必要があります。リモートリソースがローカルに存在しない場合、Pushエントリが作成されます(これには挿入/更新の実際のデータが含まれます)。リモートトランザクションログに存在しないローカルリソースは変更されていないと見なされます。

プルリクエストはリモートノードに対して行われるため、itemURIを使用してローカルにデータが存在します。それらは後でローカルに適用されません。

手順3-ローカル同期トランザクションログをリモートにプッシュする

Local:PUT /remotehost/items/transactions本文にローカル同期トランザクションログが含まれています。

リモートノードは、オーバーヘッドが大きくなる可能性がある場合、これを同期的に(小規模で迅速な場合)または非同期的に202 ACCEPTEDと考えて処理します。同期操作を想定すると、成功または失敗に応じて、結果は200 OKまたは409 CONFLICTになります。 409 CONFLICTの場合、リモートノードで楽観的ロック障害が発生したため(同期中にデータが変更されたため)、プロセスを再度開始する必要があります。リモート更新は、独自のアプリケーショントランザクションで処理されます。

ステップ4-ローカルで更新

手順2で取得したデータは、アプリケーショントランザクションの下でローカルに適用されます。

上記は完全ではありませんが(ローカルとリモートで問題が発生する可能性があり、ローカルからリモートプルデータを取得する方が大きなPUTに詰め込むよりも効率的である可能性があります)、RESTの使用方法を示しています。双方向同期プロセス中。

18
Gary Rowe

同期操作は、アクセス(GET)または作成(POST)できるリソースと見なします。これを念頭に置いて、API URLは次のようになります。

/todo_services/abc123/synchronization

(動詞ではないことを明確にするために、「同期」ではなく「同期」と呼びます)

次に行います:

POST /todo_services/abc123/synchronization

同期を開始します。同期操作はリソースであるため、この呼び出しは、操作のステータスを確認するために使用できるIDを返す可能性があります。

GET /todo_services/abc123/synchronization?id=12345
6
laurent

これは難しい問題です。 RESTは同期を実装するのに適切なレベルです。堅牢な同期は本質的に分散トランザクションである必要があります。RESTはそのためのツールではありませんジョブ。

(前提条件:「同期」とは、どちらかのリソースがいつでも他方から独立して変更できることを意味しており、更新を失うことなくそれらを再調整する機能が必要です。)

マスターからのデータで定期的にスレーブを確実に処理できるように、一方を「マスター」、もう一方を「スレーブ」にすることを検討することをお勧めします。

個別に変更するデータストアをサポートする必要がある場合は、 Microsoft Sync Framework を検討することもできます。これはRESTでは機能しませんが、舞台裏で機能します。

5
codingoutloud

Apache CouchDB は、REST、HTTP、JSONに基づくデータベースです。開発者はHTTPを介して基本的なCRUD操作を実行します。また、HTTPメソッドのみを使用するピアツーピアのレプリケーションメカニズムも提供します。

このレプリケーションを提供するには、CouchDBにCouchDB固有の規則がいくつか必要です。 RESTに反対するものはありません。各ドキュメント(つまり、データベース内のRESTリソース))に リビジョン番号 を提供します。これはそのドキュメントのJSON表現の一部ですが、 ETag HTTPヘッダー各データベースには、データベース全体に対して 変更の追跡 を許可するシーケンス番号もあります。

conflict resolution の場合、ドキュメントが競合していること、および競合したバージョンを保持していることに単に気づき、データベースを使用して競合解決アルゴリズムを提供する開発者に残します。

REST APIとしてCouchDBを使用すると、すぐに同期を行うことができます。あるいは、独自のアルゴリズムを作成するための開始点を提供するレプリケーションを提供する方法を確認することもできます。

2
David V