REST APIで双方向同期をどの程度最適に表現しますか?


23

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

例:

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

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

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

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

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

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

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

ある種のRPCでは、次のことができます

POST / todo_services / abc123 / sync /

しかし、「動詞は悪い」という考えでは、このアクションを表現するより良い方法はありますか?


4
優れたAPI設計は、同期の意味を非常に具体的に理解することに絶対的に依存していると思います。通常、2つのデータソースの「同期」は非常に複雑な問題であり、単純化するのは非常に簡単ですが、その影響をすべて考慮することは非常に困難です。それを「双方向」同期にすると、突然難易度が非常に高くなります。出てくる非常に難しい質問を熟考することから始めます。
アダムクロスランド

正しい-同期アルゴリズムが「コードレベル」APIで設計され機能していると仮定します-これをRESTで公開するにはどうすればよいですか。一方向の同期ははるかに簡単に表現できます:私GET /todo/1/POSTそれへ/todo_services/abc123/ の2つの方法-データセットを取得してリソースにPUTするのではなく、実際に実行するアクションにより、2つのリソースが変更される可能性があります。私は、リソースそのものが「藤堂syncronizations」を有するに頼ることができると思います POST /todo_synchronizations/ {"todos":["/todo/1/","/todo_services/abc123/1"],"schedule":"now"}
エドワード・M・スミス

私たちはまだ馬術前の問題を抱えています。私のポイントは、同期が機能することを想定してAPIを設計することはできないということです。APIの設計は、同期アルゴリズムが正確にどのように機能するかについての多くの懸念によって推進されます。
アダムクロスランド

これにより、有用な結果が潜在的に公開されます。 GET /todo_synchronizations/1=>{"todos":["/todo/1/","/todo_services/abc123/1"],"schedule":"now","ran_at":"datetime","result":"success"}
エドワードMスミス

2
@Adamに同意します。同期の実装方法を知っていますか?変更をどのように処理していますか?調整するアイテムのセットが2つあるだけですか、それとも最後の同期以降に2つのセットが発散したアクションのログがありますか?私が尋ねる理由は、(RESTに関係なく)追加と削除を検出するのが難しい場合があるからです。サーバー側にオブジェクトがあり、クライアント側にない場合は、「クライアントがそれを削除したのか、サーバーが作成したのか」と自問する必要があります。「リソース」の動作を正確に知っている場合にのみ、RESTでそれを正確に表すことができます。
レイモンドサルトレリ

回答:


17

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

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

質問は次のようになります。リソースの観点から同期についてどう考えるか。

双方向同期とは**

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

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

ステップ1-ローカルはトランザクションログを取得します

地元: GET /remotehost/items/transactions?earliest=2000-01-01T12:34:56.789Z

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

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

  • updatedAt -データが最後に更新されたときに調整されたポイントを提供するタイムスタンプ(改訂履歴は必要ないと仮定)

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

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

ステップ2-ローカルは、リモートトランザクションログを独自のログと比較します

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

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

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

ローカル: PUT /remotehost/items/transactionsローカル同期トランザクションログを含む本文。

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

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

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

上記は完全ではありませんが(ローカルおよびリモートで問題が発生する可能性があり、ローカルからリモートプルデータを取得する方が、大きなPUTにデータを詰め込むよりも効率的である場合があります)、Bi-方向同期プロセス。


6

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

/todo_services/abc123/synchronization

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

それから:

POST /todo_services/abc123/synchronization

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

GET /todo_services/abc123/synchronization?id=12345

3
この簡単な答えが答えです。動詞を名詞に変えて
先に進み

5

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

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

マスターからのデータで定期的にスレーブを自信を持って上書きできるように、一方を「マスター」、もう一方を「スレーブ」にすることを検討する必要があります。

独立して変更するデータストアをサポートする必要がある場合は、Microsoft Sync Frameworkを検討することもできます。これはRESTを介しては動作しませんが、背後で動作します。


5
「難しい問題」の場合は+1。双方向の同期は、泥の奥深くに到達するまでそれがどれほど難しいかを理解していないものの1つです。
ダン・レイ・

2

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

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

以下のために紛争解決、彼らは単に競合解決アルゴリズムを提供するために、データベースを使用して開発者にそれを残して、文書が競合であることに注意して競合するバージョンを保持します。

CouchDBをREST APIとして使用して、すぐに同期できるようにするか、複製を提供して独自のアルゴリズムを作成するための開始点を提供する方法を確認できます。


私はCouchDBが大好きで、後継のCouchBase + SyncGatewayです。+1
レオニードウソフ

-1

単純な名前変更で「動詞が悪い」問題を解決できます-「同期」の代わりに「更新」を使用します。

同期プロセスは、実際には最後の同期以降に行われたローカル更新のリストを送信し、同じ時間にサーバーで行われた更新のリストを受信します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.