ステートレスとは何か
» Permanent link | |
RestWiki をたまに見直すと新たな発見があって面白い。
たとえば先日、「ステートレスなやりとりとは何か(What is Stateless Interaction?)」という箇所を見つけて、興味深く読んだ。このページは以前も絶対に読んでいるはずなのだが、 人間は忘れてしまうものである。
RestWiki の例でも充分わかりやすいのだけれど、自分でも例を思いついたので書きとめておく。
ステートフルサーバとステートレスサーバはどう違うのか。
まずは、ステートフルの例:
- 客: こんにちは
- 店員: いらっしゃいませ。○○バーガーへようこそ
- 客: ハンバーガーセットをお願いします
- 店員: サイドメニューは何になさいますか?
- 客: ポテトで
- 店員: ドリンクは何になさいますか?
- 客: ジンジャーエールで
- 店員: +50円でドリンクをLサイズにできますがいかがですか?
- 客: Mでいいです
- 店員: 以上でよろしいですか?
- 客: はい
- 店員: かしこまりました
これはいたって普通の会話に見える。では、ステートレスな場合はどうなのか。
- 客: こんにちは
- 店員: いらっしゃいませ。○○バーガーへようこそ
- 客: ハンバーガーセットをお願いします
- 店員: サイドメニューは何になさいますか?
- 客: ハンバーガーセットをポテトでお願いします
- 店員: ドリンクは何になさいますか?
- 客: ハンバーガーセットをポテトとジンジャーエールでお願いします
- 店員: +50円でドリンクをLサイズにできますがいかがですか?
- 客: ハンバーガーセットをポテトとジンジャーエール(M)でお願いします
- 店員: 以上でよろしいですか?
- 客: ハンバーガーセットをポテトとジンジャーエール(M)でお願いします。以上
- 店員: かしこまりました
これは明らかに冗長であほらしいのだけれど、サーバがステートレスというのはこういうことである。
ステートフルの例では、2回目以降の対話では、客(クライアント)はそれまでの前提(ハンバーガーセットを頼んでいること)は 繰り返さなくてもよかった。なぜか。それは店員(サーバ)が客(クライアント)の注文状態を覚えていたからである。 この店員(サーバ)は「この客(クライアント)はハンバーガーセットをポテトで頼んでいる」ということを覚えている。 これをアプリケーション状態、あるいはセッション状態と呼ぶ。 次にドリンクの種類を聞いたときに店員(サーバ)は自分で覚えている客(クライアント)のアプリケーション状態を 「この客はハンバーガーセットをポテトとジンジャーエールで頼んでいる」と更新する。
ファーストフード店の店員であれば、ステートフルな実装は当たり前なのだが、Web サーバは異なる。 それはスケーラビリティの問題である。 店員(サーバ)が一人の客(クライアント)をずっと相手にしていると、その間別の客に対応することができない。 店が込んできたら(アクセスが集中したら)、店員を増員して(Webサーバを増設して)対応する。 普通の店舗では、ひとつのレジで一人の店員がずっと同じ客を受け付けるのだが、 Web の場合は複数の Web サーバ(比較的少数)で複数のクライアント(比較的多数)を同時に受け付ける。 ここで、ステートレスサーバであれば、以下のように、各インタラクションで別々の店員(サーバ)が 客(クライアント)の注文(リクエスト)に応答(レスポンス)することが可能になる。
- 客: こんにちは
- 店員1: いらっしゃいませ。○○バーガーへようこそ
- 客: ハンバーガーセットをお願いします
- 店員2: サイドメニューは何になさいますか?
- 客: ハンバーガーセットをポテトでお願いします
- 店員3: ドリンクは何になさいますか?
- 客: ハンバーガーセットをポテトとジンジャーエールでお願いします
- 店員4: +50円でドリンクをLサイズにできますがいかがですか?
- 客: ハンバーガーセットをポテトとジンジャーエール(M)でお願いします
- 店員5: 以上でよろしいですか?
- 客: ハンバーガーセットをポテトとジンジャーエール(M)でお願いします。以上
- 店員6: かしこまりました
ステートレスサーバというのは一見冗長なように見えるが、 スケーラビリティの観点から見ると、理に適っているものである。
合わせて読みたい: A Web-Centric Approach to State Transition
ラベル: rest
4 Comments:
にっくと申します。通りがかりのコメント失礼いたします。
RESTのステートレスの議論で疑問に思うのは、「ステートフル/ステートレス」という設計議論はRESTと直交する考えではないか? という点です。
たとえば、
・ショッピングカート内容をDBサーバに保存する
・ユーザ登録情報をDBサーバに保存する
こうしたWebサイトは、アプリサーバはステートレスになりますが、クライアントからは「ステートフルなサーバ」として見えますので、以前に送信したリクエストを再送する必要はありません。
RESTfulなサイトにするには、カート内容をDBサーバに保存せず、毎回URI上で指示すべきなのでしょうか? そんなことしなくても、RESTの恩恵は十分に受けられると私は思うのですが、いかがでしょうか。
RESTful を「Roy Fielding の論文に載っているアーキテクチャ制約をなるべく満たしている」と定義するなら、ステートレスではないからといって即刻 RESTful でなくなることはないですね。ステートフルだけど、統一インターフェース、階層化システムを利用して、いる RESTful なシステムも考えられます。
> ・ショッピングカート内容をDBサーバに保存する
ショッピングカートリソースを作り、そのリソースにURIを与え、そこに商品を追加し、ステートレスにそのカートにアクセスできるのなら RESTful だと思います。
> ・ユーザ登録情報をDBサーバに保存する
ユーザリソースをつくり、そのリソースに URI を与え、ステートレスにそのカートにアクセスできるのなら RESTful だと思います。
> RESTfulなサイトにするには、カート内容をDBサーバに保存せず、毎回URI上で指示すべきなのでしょうか?
これは設計の問題です。このエントリの例はステートレスとステートフルの違いを単純化して強調していますが、RESTful にショッピングカートを設計する方法はたくさんあります。
・すべてのリクエストに商品情報をすべて含めるパターン
・ショッピングカートリソースを作るパターン
・Ajax 的にクライアント側でカート情報を保持するパターン
などがあると思います。
なるほど、ステートフルだけどRESTfulなシステムというのもありえるのですね。お返事ありがとうございました。
突然失礼いたします。
zouともうします。
大変わかりやすい例えで、
すんなり理解ができました♪
ありがとうございます。
コメントを投稿
<< Home