ステートフルとステートレスの違いは気が利く奴か否か
ステートフルとは、状況によって、あるリクエストをしたら、レスポンス (対応や反応、応答内容等) が変わるもの。特に、それ以前のやり取りの状況 (ステート) によって回答が変わるものを言います。
つまり、それまでの会話の文脈やニュアンスを踏まえてリクエストを理解し、臨機応変に適した回答をする、気の利く奴のことです。
ステートレスとは、状況によらず、あるリクエストをしたら、必ず同じ結果になるもの。特に、それまでのリクエスト・レスポンスのことは一切考えず、今来たリクエストを額面通りに受け取って回答するものを言います。
つまり、1 歩歩いたら前のやり取りはもう忘れる、それまでの会話の文脈やニュアンス、空気などを一切読まずマイペースな回答をする、気の利かない奴のことです。
IPv6のアドレス払い出し方式の例
例えば IPv6 の RS/RA による IPv6 アドレス配布(ステートレス自動設定)においては、PC が RS で要求すれば、ルータはどんな状況でも 同じ回答 (/64 のプレフィックス) を RA で返しますので、その結果 PC に割り当たる IPv6 アドレスも毎回同じです。
一方、DHCPv6 による IPv6 アドレスは、プレフィックスだけでなく後半64bitも含めた 128 bit のアドレスを返します。他の端末への払い出し状況によって、回答する IPv6 アドレスは変わりますので、ステートフルです。
また、いきなり DHCP Request を受け取っても応答せず、必ず DHCP Discover から始まる、という点もステートフルです。
[ステートレスなプロトコルの例]
[ステートフルなプロトコルの例]
HTTPはステートレスなの?
ステートレスです。
HTTP の代表的なメソッドは、ファイルをダウンロードする GET、情報を Web サーバへ送る POST がありますが、それまでのリクエスト・レスポンスには一切影響されず、同じリクエストなら必ず同じ結果(レスポンス)になります。
ログイン情報を維持するHTTP
でも楽天とかでログインして買い物するときって、ログイン情報とか買い物かご情報とか状況に応じてサイトの遷移(回答)が違いますよね?
これは HTTP 通信の中に Cookie(クッキー)と呼ばれるセッション情報を含ませており、これによってステートフルな環境を提供しているのです。
なお、Cookie は HTTP の規格には正式には含まれていないため、やはりプロトコルとしては正式にステートレスなままですが、この Cookie は非常に頻繁に根強く使われています。
HTTPはステートレスなのにステートフル・インスペクションには引っ掛かるの?
はい、引っ掛かります。
「ステートフル」と「ステートレス」という言葉はアプリケーション層での考え方とネットワーク層での考え方で違います。今までの説明はどちらかというとアプリケーション層での考え方になります。
一方、ネットワーク層での考え方で「ステートフル」というと一般にステートフル・インスペクションのことを示します。
この機能は、『そのパケット単体を見るのではなく、それまでの会話の文脈やニュアンスを汲み取って、正しいと思われる会話のみを許可する』ものですが、これは主に IP, TCP/UDP に対して行われる検査です (例えば TCP syn の後に TCP syn/ack が返ってきているか、等) ので、その上位層であるプロトコル (http,dns,smtp等なんでも) であれば、ステートフル/ステートレスに関係なく適用可能です。
つまり、ステートフル・インスペクションは、ステートレスなプロトコルのあるリクエストに対するレスポンスが、妥当なものかを検査し、問題なければ許可、問題があれば拒否する、といったことができます。
AWS におけるステートフル/ステートレス
AWS ではステートフル/ステートレスという言葉は基本的には冒頭の説明のアプリケーション層での考え方を指していると考えてよいでしょう。ただ、ネットワーク ACL、セキュリティグループの比較時に出てくる場合はネットワーク層を意味しています。
つまり、セキュリティグループのステートフルとはステートフルインスペクションを意味しています。
ステートフルとステートレスはどっちが優れているのか?
一般的にどちらが優れている、というのはありません。どちらも使い方次第です。
ただ、ネットワーク層についてはステートフルが便利、アプリケーション層はステートレスが便利、というのが個人的な見解です。
ネットワーク層のステートフル・インスペクションはその機能を見て頂ければ分かるでしょう。複雑な処理を自動でやってくれるので、メーカーがバグ無くしっかり作ってくれれば制御がとても楽ちんですし実際あまりバグにはぶち当たりません。
一方、アプリケーションについてはできるだけステートレスに作るべきです。例えば AWS のアーキテクチャや特徴を見てもそれがよくわかります。
ある Web アプリケーションサーバを3台構築してロードバランサで負荷分散する際、ステートフルなアプリケーションの場合は特定のクライアントからの通信を必ず同じサーバに振り向ける必要があります。一方、ステートレスなアプリケーションの場合は特に気にせずそのタイミングで空いているサーバに振り向けることができます。
負荷分散装置には「スティッキーセッション」という機能があり、この負荷分散の話に限っては大した話ではありません。しかし、例えば「スケールアウト」する場合はどうでしょう?
AWS では複数サーバのいずれも負荷が向上した際に、追加サーバを自動で起動する「オートスケール」という機能があります。これを使って起動した4台目のサーバへの通信を振り分ける際、ステートフルである場合は「スティッキーセッション」機能のせいで4台目への効率的な負荷分散が阻害されてしまいます。
その他、スポットインスタンスを有効活用したい場合は、いつ停止になるか分かりませんので、ステートレスに作っておけば処理の中断も行いやすいでしょう。
コメント