この中で 記事 著者はそれを主張している
場合によっては、本質的にRESTfulでない操作をAPIで公開する必要があります。
そしてそれ
APIのアクションが多すぎる場合は、RESTfulの原則を使用するのではなく、RPCの視点で設計されているか、問題のAPIがRPCタイプモデルに適していることを示しています。
これは、私が他で読んだり聞いたりしたことも反映しています。
しかし、これは非常に混乱しているので、この問題をよりよく理解したいと思います。
VMのシャットダウンをモデル化するには、根本的に異なる2つの方法があると思います。それぞれの方法にはいくつかのバリエーションがあるかもしれませんが、今のところ最も基本的な違いに集中しましょう。
PATCH /api/virtualmachines/42
Content-Type:application/json
{ "state": "shutting down" }
(または、サブリソースのPUT
/api/virtualmachines/42/state
。)
VMはバックグラウンドでシャットダウンします。シャットダウンは成功するか、電源オフで状態が内部的に更新されないかによって、しばらくしてからシャットダウンされます。
PUT /api/virtualmachines/42/actions
Content-Type:application/json
{ "type": "shutdown" }
結果は最初の例とまったく同じです。状態はすぐに「シャットダウン」に更新され、最終的には「電源オフ」に更新されます。
どちらのデザインもRESTfulですか?
どのデザインが良いですか?
複数の集約の更新につながる可能性がある、または具象リソースとサブリソースのCRUD操作にマップできない可能性のある「アクション」(別名コマンド)が多数あるCQRSドメインがある場合はどうなりますか?
可能な限り、具象リソースに対する具象作成または更新と同じくらい多くのコマンドをモデル化して(例Iの最初のアプローチに従って)、残りに「アクションエンドポイント」を使用する必要がありますか?
または、すべてのコマンドをアクションエンドポイントにマッピングする必要がありますか(例Iの2番目のアプローチのように)?
どこに線を引くべきですか?設計がRESTfulでなくなるのはいつですか?
CQRSモデルはRPCのようなAPIに適していますか?
上記の引用テキストによると、私が理解しているとおりです。
私の多くの質問からわかるように、私はこのトピックについて少し混乱しています。それをよりよく理解するのを手伝ってくれませんか?
最初のケース(VMのシャットダウン)では、RESTfulなOPの代替案はありません。確かに、 Richardson成熟度モデル を尺度として使用する場合、リソースと動詞を使用するため、両方がレベ2APIです。
ただし、どちらもハイパーメディアコントロールを使用しておらず、私の意見では、これはRPCからの唯一のタイプREST that differentiates RESTful API design from RPC。つまり、stickレベル1および2では、ほとんどの場合、RPCスタイルのAPIを使用します。
VMをシャットダウンする2つの異なる方法をモデル化するために、VM自体を(とりわけ)リンクを含むリソースとして公開します。
{
"links": [{
"rel": "shut-down",
"href": "/vms/1234/fdaIX"
}, {
"rel": "power-off",
"href": "/vms/1234/CHTY91"
}],
"name": "Ploeh",
"started": "2016-08-21T12:34:23Z"
}
クライアントがPloeh
VMをシャットダウンする場合は、shut-down
関係タイプを使用してリンクを追跡する必要があります。 (通常、 RESTful Web Services Cookbook で概説されているように、関係タイプにはIRIまたはより複雑な識別スキームを使用しますが、この例はできるだけ単純にすることにしました。)
この場合、アクションで提供する他の情報はほとんどないため、クライアントはhref
のURLに対して空のPOSTを作成するだけです。
POST /vms/1234/fdaIX HTTP/1.1
(このリクエストには本体がないため、これをGETリクエストとしてモデル化するのは魅力的ですが、GETリクエストには目に見える副作用がないはずなので、POSTの方が正しいです。)
同様に、クライアントがVMの電源をオフにしたい場合は、代わりにpower-off
リンクをたどります。
言い換えれば、リンクの関係タイプは、意図を示すaffordancesを提供します。それぞれの関係タイプには、特定の意味上の意味があります。これがセマンティックウェブについて時々話す理由です。
例をできるだけ明確にするために、各リンクのURLを意図的に覆い隠しました。ホスティングサーバーが受信リクエストを受信すると、fdaIX
はシャットダウンを意味し、CHTY91
は電源オフを意味することがわかります。
通常、私はURL自体にアクションをエンコードするだけなので、URLは/vms/1234/shut-down
と/vms/1234/power-off
になりますが、教えるときは、関係タイプ(セマンティクス)とURL(実装)の区別が曖昧になります詳細)。
使用しているクライアントに応じて、 RESTful URLをハッキング不可能にする を検討できます。
CQRSに関しては、Greg YoungとUdi Dahanが同意する数少ないことの1つはCQRSがトップレベルのアーキテクチャではないということです。したがって、RESTful APIをCQRSのようにすることには注意が必要です。これは、クライアントがアーキテクチャの一部になることを意味します。
多くの場合、実際の(レベル3)RESTful APIの原動力は、クライアントを壊すことなく、またクライアントを制御することなく、APIを進化させたいことです。それがあなたの動機であれば、CQRSは私の最初の選択肢にはなりません。
これは実際にはいくぶん有名な例で、 Tim Bray、2009年 によって発表されました。
ロイフィールディング、問題について話し合う この観察を共有した :
個人的には、監視された状態(電源状態など)を編集不可として扱うシステムを好みます。
つまり、監視対象の状態の現在の表現を返す情報リソースが1つあります。その表現には、その状態への変更を要求するform thatへのハイパーメディアリンクが含まれる場合があり、フォームには、(各)変更要求を処理するためのリソースへの別のリンクがあります。
Seth Ladd は、問題について重要な洞察を得ました
Runningを人の単純な状態から、作成、更新、および話題にできる真の名詞に変えました。
これをマシンの再起動に戻します。私はあなたがPOST to/vdc/434/cluster/4894/server/4343/rebootsするだろうと主張します投稿したら、あなたはthisを表すURIを持っています=再起動すると、GETしてステータスを更新できます。ハイパーリンクの魔法によって、再起動の表現は再起動されたサーバーにリンクされます。
URIスペースの作成は安価であり、URIはさらに安価だと思います。名詞としてモデル化されたアクティビティのコレクションを作成し、POST、PUT、DELETEを実行します。
RESTfulプログラミングは、WebスケールのVogon官僚機構です。 anything RESTfulをどのように実行しますか?そのための新しい書類を発明し、書類をデジタル化します。
やや洗練された言語では、「仮想マシンをシャットダウンする」ためにドメインアプリケーションプロトコルを定義し、そのプロトコルを公開/実装するために必要なリソースを特定しています。
自分の例を見る
PATCH /api/virtualmachines/42
Content-Type:application/json
{ "state": "shutting down" }
それで大丈夫です;リクエスト自体を独自の個別の情報リソースとして実際に処理しているわけではありませんが、それでも管理できます。
変化の表現を少し見逃しました。
ただし、PATCHでは、囲まれたエンティティに、現在Originサーバーにあるリソースを変更して新しいバージョンを作成する方法を説明する一連の指示が含まれています。
たとえば、 JSON Patch メディアタイプは、JSONドキュメントを直接変更しているかのように命令をフォーマットします
[
{ "op": "replace", "path": "state", "value": "shutting down" }
]
あなたの代わりに、アイデアは近いですが、明らかに正しいわけではありません。 PUT
はリソースの状態を完全に置き換えたものですターゲットURLでなので、collectionのようなスペルを選択することはおそらくないでしょう。 singleエンティティの表現のターゲット。
POST /api/virtualmachines/42/actions
キューにアクションを追加しているというフィクションと一致しています
PUT /api/virtualmachines/42/latestAction
キューの最後の項目を更新しているというフィクションと一致しています。この方法で行うのは少し変です。最小の驚きの原則は、すべてのPUTを1つの場所に配置して複数のリソースを同時に変更するのではなく、各PUTに固有の識別子を与えることをお勧めします。
URIのスペルについて説明している限り、-RESTは関係ありません; /cc719e3a-c772-48ee-b0e6-09b4e7abbf8b
は、RESTに関する限り、完全なURIです。読みやすさは、変数名と同様に、別の問題です。 RFC 3986 と一致するスペルの使用peopleがもっと楽しくなります。
複数の集約の更新につながる可能性がある、または具象リソースとサブリソースのCRUD操作にマップできない可能性のある「アクション」(別名コマンド)が多数あるCQRSドメインがある場合はどうなりますか?
CQRSは非常に単純なパターンであり、他の方法では存在しない可能性があるアーキテクチャの多くの機会を可能にします。 CQRSは結果整合性ではなく、イベント発生ではなく、メッセージングではなく、読み取りと書き込みのモデルが分離されておらず、イベントソーシングを使用していません。
ほとんどの人がCQRSについて話すとき、彼らは本当にアプリケーションのサービス境界を表すオブジェクトにCQRSパターンを適用することについて話しています。
HTTP/RESTのコンテキストでCQRSについて話していることを考えると、この後者のコンテキストで作業していると想定するのは理にかなっているようです。
これは驚くべきことに、前の例よりもさらに簡単です。これの理由は単純です:コマンドはメッセージです。
Jim Webber は、1950年代のオフィスのアプリケーションプロトコルとしてHTTPについて説明しています。仕事は、メッセージを受け取り、受信トレイに入れることによって行われます。同じ考えが成り立ちます-私たちはフォームの空のコピーを取得し、私たちが知っている詳細を記入して、それを配送します。多田
可能な限り、具象リソースに対する具象作成または更新と同じくらい多くのコマンドをモデル化して(例Iの最初のアプローチに従って)、残りに「アクションエンドポイント」を使用する必要がありますか?
はい、「具体的なリソース」がドメインモデルのエンティティではなくメッセージである限り。
重要なアイデア:REST APIはインターフェイスのままです。クライアントがメッセージを変更する必要なく、基になるモデルを変更できるはずです。新しいモデルをリリースするとき、ドメインプロトコルを取得して新しいモデルに適用する方法を知っているWebエンドポイントの新しいバージョンをリリースします。
CQRSモデルはRPCのようなAPIに適していますか?
特にありません。特に、Webキャッシュは「結果的に一貫した読み取りモデル」の良い例です。各ビューを個別にアドレス指定可能にし、それぞれに独自のキャッシュルールを設定すると、無料で大量のスケーリングを利用できます。読み取りに対するRPCのみのアプローチには、あまり魅力がありません。
書き込みの場合、これはよりトリッキーな質問です。単一のエンドポイントまたは単一のエンドポイントファミリーの単一のハンドラーにすべてのコマンドを送信することは、確かに簡単です。 RESTは、エンドポイントがクライアントに通信する場所を見つける方法についての詳細です。
メッセージを独自の固有のリソースとして扱うことには、PUTを使用できるという利点があります。中間コンポーネントにメッセージの処理がべき等であることを警告し、エラー処理の特定のケースに参加できるので便利です。 。 (注:クライアントの観点から見ると、リソースのURIが異なる場合、それらは異なるリソースです。Originサーバー上ですべて同じリクエストハンドラーコードを持つ可能性があるという事実は、ユニフォームによって隠された実装の詳細ですインターフェース)。
上記はまだ完全にRESTfulではないことにも注意してください。少なくとも私がこの用語をどのように使用しているか。私がやったことはすべて、RPCに過ぎないサービスインターフェースについての説明です。 RESTfulにするためには、サービスを導入して定義するハイパーテキストを追加し、フォームやリンクテンプレートを使用してマッピングを実行する方法を説明し、視覚化を便利な方法で組み合わせるコードを提供する必要があります。
5レベルのメディアタイプ を利用して、リクエストのcontent-typeヘッダーフィールドにコマンドを指定できます。
VMの例では、これらの線に沿ったものになります
PUT /api/virtualmachines/42
Content-Type:application/json;domain-model=PowerOnVm
> HTTP/1.1 201 Created
Location: /api/virtualmachines/42/instance
その後
DELETE /api/virtualmachines/42/instance
Content-Type:application/json;domain-model=ShutDownVm
または
DELETE /api/virtualmachines/42/instance
Content-Type:application/json;domain-model=PowerOffVm
リンクされた記事の例は、モデル化されたリソースの状態の変化ではなく、コマンドによってマシンを起動およびシャットダウンする必要があるという考えに基づいています。後者は、RESTが生きて呼吸するものとほぼ同じです。 VMのより良いモデリングには、実際の対応物がどのように機能するか、そして人間としてのそれとどのように相互作用するかを検討する必要があります。これは長い間ですが、良いモデリングを行うために必要な思考のタイプについての良い洞察を与えると思います。
机の上のコンピュータの電源状態を制御する方法は2つあります。
VMの場合、これらの両方をブール値の読み取り/書き込みとしてモデル化できます。
power
-true
に変更すると、スイッチがこの状態になったことを通知する以外は何も起こりません。 false
に変更すると、VMは即時電源オフ状態になるように命令されます。完全を期すために、書き込み後に値が変更されていない場合、何も起こりません。
onoff
-true
に変更した場合、power
がfalse
の場合は何も起こりません。それ以外の場合は、VMを開始するように命令します。 false
に変更した場合、power
がfalse
の場合は何も起こりません。それ以外の場合は、VMは、ソフトウェアに通常のシャットダウンを実行するように通知するように命令されます。電源オフ状態になる可能性があります。繰り返しになりますが、完全を期すために、変更なしの書き込みは何もしません。
これにより、マシンの状態がスイッチの状態を反映していない状況が1つあり、それがシャットダウン中に発生することがわかります。 power
は引き続きtrue
で、onoff
はfalse
のままですが、プロセッサはシャットダウンを実行しているため、別のリソースを追加して、マシンが実際に何を行っているかを確認する必要があります。
running
-VMが実行されている場合はtrue
であり、実行されていない場合はfalse
である読み取り専用の値。ハイパーバイザの状態を確認することで決定されます。この結果、VMを起動する場合は、power
およびonoff
リソースがtrue
に設定されていることを確認する必要があります。 (power
ステップを自動リセットすることでスキップできるようにすることができます。そのため、false
に設定すると、VMが検証可能にハードストップされた後、true
になります。それがRESTfulに純粋なものかどうか正常にシャットダウンする場合は、onoff
をfalse
に設定し、後で戻ってマシンが実際に停止したかどうかを確認します。そうでない場合は、power
をfalse
に設定します。
現実の世界と同様に、VMをonoff
をfalse
に変更した後、VMを開始するように指示されるという問題がありますが、シャットダウンの途中であるため、依然としてrunning
です。あなたがそれにどう対処するかは政策決定です。
どちらのデザインもRESTfulですか?
したがって、安静に考えたい場合は、コマンドを忘れてください。クライアントはサーバーにVMをシャットダウンするように指示しません。クライアントは、状態を更新してリソース表現のコピーを「隠し」(比喩的に言えば)、サーバーにその表現をPUTします。サーバーはその新しい状態表現を受け入れ、これの副作用として、実際にはVMをシャットダウンします。副作用の側面はサーバーに任されています。
少ない
ちょっとサーバー、ここにクライアント、VMをシャットダウンしてよろしいですか
などの
ちょっとサーバー、ここにクライアント、私はリソースの状態を更新しましたVM 42をシャットダウン状態にして、このリソースのコピーを更新してから、適切だと思うことをすべて実行してください
この新しい状態を受け入れるサーバーの副作用として、サーバーは実際に実行する必要があるアクション(物理的にシャットダウンするVM 42)など)を確認できますが、これはクライアントに対して透過的です。クライアントこの新しい状態と一致するためにサーバーが実行する必要があるアクションには関係ありません
コマンドを忘れてください。唯一のコマンドは、状態転送のためのHTTPの動詞です。クライアントは、サーバーが物理的なVM=をシャットダウンの状態にする方法)を知りませんし、気にしません。クライアントは、サーバーにコマンドを発行せず、これはただ言っているだけですこれは新しい状態です、理解してください。
これの威力は、フロー制御の観点から、クライアントをサーバーから切り離すことです。後でサーバーがVMでの動作を変更しても、クライアントは気にしません。更新するコマンドエンドポイントはありません。 RPCでは、APIエンドポイントをshutdown
からshut-down
に変更すると、サーバーで呼び出すコマンドがわからなくなるため、すべてのクライアントが壊れます。
RESTは宣言型プログラミングに似ており、何かを変更するための一連の指示をリストする代わりに、希望する方法を記述して、プログラミング環境にそれを認識させます。