HTTPのステートレス性とHTTPメソッドの冪等性などについて

「Webを支える技術」を読んでいます。
大雑把にしか知らなかった飛び飛びの知識が穴埋めされていくようで読んでいてとても楽しいです。

ステートレス(stateless)とは

HTTPはステートレスなプロトコルです。
ステートレスというのは状態(state)を管理しない(less)ということです。
HTTPで言うと、サーバがクライアントの状態を保存しない制約のことです。

サーバとクライアントのやりとりにおいて、HTTPでは文脈とかニュアンスとか関係はありません。
話が一つ進めば、もうそれまでのことは全く覚えていないのです。

本で紹介されていたクライアント(客)とサーバ(店員)のやりとりです。
以下の会話は以下のサイトから引用させてもらいました。
【参考】yohei-y:weblog: ステートレスとは何か

ステートレスな店員の例

客: こんにちは
店員: いらっしゃいませ。○○バーガーへようこそ
客: ハンバーガーセットをお願いします
店員: サイドメニューは何になさいますか?
客: ハンバーガーセットをポテトでお願いします
店員: ドリンクは何になさいますか?
客: ハンバーガーセットをポテトとジンジャーエールでお願いします
店員: +50円でドリンクをLサイズにできますがいかがですか?
客: ハンバーガーセットをポテトとジンジャーエール(M)でお願いします
店員: 以上でよろしいですか?
客: ハンバーガーセットをポテトとジンジャーエール(M)でお願いします。以上
店員: かしこまりました

ステーフルな店員の例

客: こんにちは
店員: いらっしゃいませ。○○バーガーへようこそ
客: ハンバーガーセットをお願いします
店員: サイドメニューは何になさいますか?
客: ポテトで
店員: ドリンクは何になさいますか?
客: ジンジャーエールで
店員: +50円でドリンクをLサイズにできますがいかがですか?
客: Mでいいです
店員: 以上でよろしいですか?
客: はい
店員: かしこまりました

ステートレスな会話はすごい冗長な感じがしますね。
なんだかこれだけ見ると「HTTPがスレートレスであること」はデメリットのようにも感じられますが、メリットはどこにあるのでしょうか。

また、ショッピングサイトなど、最初にログインして、カートに入れ、クレジットカードを登録し、注文確定するなどのよくあるサービスでは、どうやって状態を管理しているのでしょうか。

ちなみにステートレスなものとステートフルなプロトコルの例は以下のような感じです。

ステートレスなプロトコル

HTTP, UDP, IP, DNS, etc.

ステートフルなプロトコル

FTP, TCP, BGP, OSPF, EIGRP, SMTP, SSH, etc

メリデメ

ステートレス性、ステートフル性、各々のメリット・デメリットを比較してみます。

スレートレス性のメリット

  • リクエストもレスポンスも常にリソースに対する過不足ない情報になる
  • クライアントが増えてもサーバの台数を増やすだけで対応できるのでスケールアウトに向いている
  • サーバ側の処理や実装がシンプルになる

ステートフル性のメリット

  • やりとりが簡潔なのでネットワーク帯域を節約できる

ステートレスのデメリット

  • やりとりが冗長になりがち
  • リソースに対する操作が必要になるたびに、同じやりとりを繰り返す
  • なので、ネットワーク帯域を消費し処理が遅くなる
  • さらに、データベースなどへのアクセスが増えるので処理に時間がかかる
  • エラーが起きたとき辛い(後述)

ステートフルのデメリット

  • クライアントの状態を把握する必要があるので、クライアントの数が増えると負荷も増える
  • 複数のサーバがある場合、サーバ間で一クライアントの状態を同期する必要がある
  • だから、この同期にかかる処理のオーバーヘッドが生じる
  • なので、スケールアウトに向かない

通信エラー時の対応の違いについて

ステートレスのデメリットの最後にあった「通信エラーが起きたときに辛い」というのは、例えばショッピングサイトの注文確定時などにこんなことが起こりえます。

クライアント「これを注文しまー(ガサゴソ」
サーバ「え、なんて?注文確定ね?」
クライアント「あれ?今ミスった?もっかい言っとこ。注文しまーす」
サーバ「おっけー(2個買うんやな)」

状態を管理していないので、一度注文したことに気づかず、重複して注文してしまいました。
これがもしステートフルなものの場合は、サーバは注文されていることを知っているので2度目の注文時に「すでに1個注文してるぞ?」と聞き返すことができます。

HTTPメソッドの冪等性と安全性について

少し関連して、8つのHTTPメソッドの中に冪等性だったり、安全性などの特性を持つものがあります。
冪等なのはGET(データを取ってくるやつ),HEAD(ヘッダを返すやつ),PUT(データを更新するやつ),DELETE(データを削除するやつ)。

冪等性というのは、何度その処理を繰り返し実行しても結果が同じになるような性質のことです。

数学の分野の話に持ち込めば、ある数字に1回0をかけようが100000回0をかけようが結果は同じく0であるようなものです。

つまり、これら4つはメソッドは同じものを実行すれば、何度実行しようとも結果は同じものになります。

また、この4つのメソッドの中でもGETとHEADに関しては、値の変更をしないので「安全」であると言ったりします。
つまり副作用がないんです。

なんだかこの前書いた純粋関数っぽいですね。

今回は詳しくは書きませんが、さきほど浮かんできた疑問「ステートレスなHTTPを使うならショッピングサイトのようなログイン認証が必要なサービスではどんなやりとりをしているのか」に関しては、以下のようなキーワードがヒントのようです。(まだよくわかっていない)

  • セッション管理機能
  • Cookie

また調べてみます。

所感

冒頭にも書きましたが、「Webを支える技術」とても良い本です。
今回の内容の関連のブログなどを調べてみると、至るところでこの本の名前が参考書籍として紹介されていました。
名著ですね。

参考

ステートフル ステートレスとはどういうことか – Sojiro’s Blog

コメントを残す