Astroの光線のサムネイル。

pubDate: 2024-03-04

author: sakakibara

web

ステートフル

ステートレス

リクエスト

レスポンス

クッキー

プロトコル

ポート

インターネット

その起源はARPANETと呼ばれるネットワークであり、アメリカの国防総省が開発したものである。 研究室や大学などに設置されたコンピュータを回線でつなぎ、ネットワークを構築した。 当時は論文やメールなどの情報を共有するためにつかわれていた。 そして徐々に、メールなど以外にもファイル共有やリモートログインなど、ネットワークを利用したプログラムが開発された。

また、コンピュータは弾道計算や暗号解読を目的として開発されたものであるので、他のコンピュータとして通信することは想定されていなかった。 それから中央集権的なコンピュータ(メインフレーム)に接続してそのコンピュータを利用するという形態が流行り、その後、コンピュータの小規模化が進むと、複数のコンピュータを連携させて処理を行うことが流行った。 このように、複数のコンピュータ(ノード)を連携させて処理を行うことを分散処理と呼ぶ。

(分散処理を必要とするシステムは多く、例えばHPC(High Performance Computing)がある。日本が誇るHPC”富岳”は432台の計算機(メインフレーム)をネットワークで連携させて計算を行っている。)

分散処理はあくまでもある施設内のコンピュータを連携させる技術であるが、これを広域に拡張するニーズが生まれた。

各企業、各家庭にコンピュータが普及し、それらをネットワークで連携させる技術が求められた。 各企業、各家庭はルーター(かつての回線交換)と呼ばれる装置によって企業から企業へ、家庭から家庭へ、家庭から企業へとデータをリレーすることができるようになった。 そのネットワークのトポロジカルな性質により、世界は小さく、6次の隣人にデータを受け渡せば世界中の人とつながることができる。 このように、世界を包むネットワークが構築された。

インターネットとは分散処理システムの一つであり、実体はルーターの集まりである。

クライアント・サーバー / リクエスト・レスポンス / プロトコル / ポート

サーバーとはサービスを提供するプログラムであり、文脈に依存してそのプログラムが動いているコンピューター自体を指すことがある。ただ、本質的にはサーバーはプログラムであるので、コンピュータを指している場合でも、プログラムだと理解しても多くの場合差し支えない。

多くの場合、サービスを提供するプログラム、すなわちサーバーは24365で動作しており、サービスを受ける側(クライアント)のリクエスト(注文)を待っている。 サーバーはクライアントから来たリクエストに対しサービスとなるレスポンスを返す。

このコンピュータとコンピュータの通信関係をクライアント・サーバーと呼ぶ。 暗黙的にリクエストやレスポンスなどといった用語を使ってしまったが、 リクエスト とはクライアントがサーバーへ送る要求のことであり、レスポンスとはサーバーがクライアントへ返す応答のことである。

また、互いに通信するコンピュータは共通の規約・手順を踏んで通信を行う必要がある。 考えてみれば当然のことだが、両者で共通の規約・手順を持たないと通信が成立しない。 ただクライアントがサーバーに謎の電気信号を送りつけてもサーバーはそれを理解できない。 サーバーは送られてきた電気信号を解釈するために一定の手順を踏む、ということをクライアントが想定していないと何を送っていいいのかわからなくなるのだ。 この規約・手順のことをプロトコルと呼ぶ。

コンピュータにはレイヤーがあり、各レイヤーで共通のプロトコルを採用する必要がある。 つまり、物理的な電気信号に関するプロトコルからデータを転送する情報に関するプロトコル、データを解釈するプロコトルなどなどである。どのようなレイヤーがあるかはOSI参照モデルやTCP/IPモデルなどがある。 OSI参照モデルは以下の7つのレイヤーがある。

これらは上から”アプセトネデブ”と覚えることが伝統となっている。 (個人的な意見だが、このモデルは下からつまり、物理レイヤーから1番、2番、… のように数えることが多く、例えば、2番のレイヤーのデータを解釈して転送するスイッチをL2スイッチなどと呼ぶこともあるので”アプセトネデブ”ではなく、“ブデネトセプア”と覚えた方がいいのではないかと思う。)

TCP/IPはプロトコルの一例である。 また、TCP/IP以外にもゲーム会社は通信の処理速度や高頻度な通信を実現するために独自のプロトコルを持っていることがある。

HTTPではリクエストとしてはGETやPOSTなどがあり、レスポンスとしてはHTMLや画像などがある。 たとえば、このブログへのレスポンスは以下のようになる。

リクエスト
curl -v https://world-zip.org/posts/web/web-basic
* Host world-zip.org:443 was resolved.
* IPv6: (none)
* IPv4: 75.2.60.5
* Trying 75.2.60.5:443...
* Connected to world-zip.org (75.2.60.5) port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
~~~省略~~~

上の例で

Terminal window
* Host world-zip.org:443 was resolved.

とある。 通常、コンピュータにはネットワークに対して一意の識別子であるIPアドレスが割り当てられているが、そのアドレスをもつコンピュータは複数の外部との通信口を持っている。 たとえば、firefoxでブログにアクセスしながら、sshでリモートログインしている場合、firefoxとsshは異なる通信口を使っている。 この通信口をポート (ポート番号 )と呼ぶ。 この場合、firefox(HTTPS)は(通常)443番ポート、sshは22番ポートを使っている。

なお、ポート番号は0から65535までの範囲で指定され、0から1023までの範囲は予約済みである。 これらはwell-knownポートと呼ばれる。 HTTPSの443番、sshの22番、HTTPの80番などはwell-knownポートである。

レスポンス
curl -i https://world-zip.org/posts/web/web-basic
HTTP/2 200
age: 0
cache-control: no-cache
cache-status: "Netlify Edge"; fwd=miss
content-type: text/html; charset=utf-8
date: Sat, 06 Apr 2024 10:28:08 GMT
netlify-vary: query
server: Netlify
strict-transport-security: max-age=31536000
x-content-type-options: nosniff
x-nf-request-id: 01HTSF7254GCHVZY1NXQ4BTKEJ
<!DOCTYPE html><html lang="ja"> <head><meta charset="utf-8"><link rel="icon" type="image/svg+xml" href="/favicon.svg">
~~~省略~~~

また、このようなコンピュータ間の通信関係をアーキテクチャスタイルと呼ぶ。

シンプルな構成だが、このアーキテクチャスタイルにはいくつか利点がある。

  1. クライアントがマルチプラットフォーム化しやすいこと
  2. クライアントがレンダリングを担当しているため、サーバー側がアプリの処理に集中できること。
  3. サーバー側のスケールアウトが容易であること。

これ以外にあるのか?というと、もちろんある。 代表的なものがP2P(Peer to Peer)である。 先程のクライアント・サーバーとは異なり、P2Pはクライアントとサーバーの役割を兼任する。 実際にtwitterやスマホゲーなどで起きる事象だが、クライアント・サーバーではサーバーにリクエストが集中することになる。 これに対して、P2Pではそういった事象を回避しやすい。 WinnyやNapsterやBitTorrentなどがP2Pの代表例である。

REST

クライアント・サーバーのアーキテクチャスタイルの一つにRESTがある。 クライアント・サーバーに以下の制約を加えたものがULCODC$SS(Uniform Layerd Code on Demand Client Cache Stateless Server)、別名RESTという。

constractiondescription
uniform interfaceインターフェースが統一されている
layered systemサーバー側のシステムは階層的に分離している
code on demandサーバーはクライアントに対して実行可能なコードを返すことができる
cacheableレスポンスはキャッシュ可能である
statelessサーバーはクライアントの状態を保持しない

なお、前知識としてクライアントが取得できるweb上の情報(ECサイトなどでの商品の価格)はリソースと呼ばれ、URIで表現される。 また、URIからリソースへの対応は全射、つまり、1つのURIに対して1つのリソースが対応するように設計されている必要がある。

RESTはこれまでのクライアント・サーバーに制限を加えタモのであるが、これ以外にもアーキテクチャスタイルはある。

最も対比すべきなアーキテクチャスタイルはSOAPである。 SOAPとはSimple Object Access Protocolの略であり、XMLベースのメッセージを使用して、異なるプログラム間で情報を交換するためのプロトコルである。

また、RESTを満たすAPIをRESTful APIと呼ぶ。 RESTful APIでないものとして以下がある。

ステートレス

クライアントの状態をサーバーが保持しないことをステートレスと呼ぶ。 なぜステートレスが重要なのか? サーバーが複数のクライアントの状態を保持していると実装が複雑になり、計算資源を(無駄に)多く消費する。 つまり、ステートレスな通信とはクライアントとサーバーが 通信の文脈に依存せずに通信を行うことである。 (買い物カゴに商品があるなどのDBに格納するまでもないような情報をDBに格納する場合でも書き出しが多くなり非効率)

だが、ECサイトでショッピングをする際、買い物かごに商品が入っている場合にそのページをリロードしてみても買い物かごの中身が消えていない。 これはクライアントが”買い物かごに商品を入れている”という状態を保持しているようにみえるが、一体どうなっているのか?

実際にステートレスを徹底しようと思ってもクライアントの状態を保持する必要がある場合がある。 このような場合、状態をクライアント側が保持しておいて、次の通信にその状態を含めてサーバーへ送信すればよいのだ。 この仕組みをcookie(クッキー)と呼ぶ。 通常、cookieの情報は一つのドメインに対して4kiB分のデータを保持することができる。

cookieはRESTの主義から外れるが、実質不可欠な技術である。 このようにRESTはあくまで理想であり、実際には例外を許容すべき場合もある。

逆に、ステートレスではなく、文脈依存の通信を行うことを ステートフルと呼ぶ。

参考

プロになるためのweb技術入門 webを支える技術