[WIP]名著と噂の「Webを支える技術」を要約してみる
GCPとか色々バックエンドやろうとしてるけど、あまりにもWEB(ネットワーク)周りが分からなさすぎるので、触って覚えるんじゃなくてちゃんと本を読んで体系的に学んでいこうと思う。
第1部 Web概論
WEBとは何か
Webで用いられる基本的な技術について
WEBは下記3つが基本的な技術になってる。
本書ではこれらの用語を中心にして色々しゃべってくね。
- URI
なんらかのリソースを指し示す識別子で、URLとURNってのから構築されるよ。リソースの場所をURLで特定して、リソースの名前をURNで特定できるよ。 - HTML
Web上で用いられる文書フォーマットだよ。ハイパーリンクで様々なリソースを紐づけて表示できる事が一番の特徴らしいよ。 - HTTP
クライアントがリクエストを送信したら、送信先からレスポンスが返ってくるルールとなっている通信規格だよ。主にWEBブラウザとWEBサーバーとのやりとりに使うんだけど、それ以外でも色々と使い道があるらしいよ。
HTTP,URI,HTMLの技術によって実現出来た事
- ハイパーメディア
様々なリソースがハイパーリンク(リンク)で結びついたシステムのこと。
従来のメディア(本とか映画とか)は順番に前から探していかないと目的のリソースにたどり着けなかったんだけど、リンクが登場してからは目的のリソースに直接たどり着ける様になって便利になったね。 - 分散システム
リンクの登場によってリソースを一か所に集中させるんじゃなくて、色んな所にリソースを分散させる事が出来る様になったよ。
リソース分散させることで処理を複数台に任せれる様になったし、膨大な情報を色んなコンピューターに置いておく事も出来る様になったね。
分散させたリソースはリンクを辿って一つにまとめれば、一元的に管理する事も可能だよ。
まとめ
とにかくハイパーリンクってのでリソースを順々に追っていける仕組みが出来た事が革命的な発明なんよ。
そのハイパーリンクって考え方をベースに、URI,HTML,HTTPの技術が発達した事で効果的に活用できる様になってきて、それらの発展の先がWEBってやつなんだね。
WEBの歴史について
WEB以前のハイパーメディア
Nelsonって人が「ハイパーテキスト」と「ハイパーメディア」って言葉を考案して色々頑張って実装しようとしたんだけど、上手くいかなかったんだってさ。なんで昔のハイパーメディアの実装が上手く行かなかったかっていうと、めっちゃ複雑なシステムを構築しようとしたからなんだって。
その後大成功したWebは、短方向のリンクしかサポートしてなかったりURIが変更されるとリンクが切れたり、バージョン管理機能が無かったりと色々不完全なシステムな様に見えるんだけど、ハイパーメディアとして最低限の機能だけを抑えたシンプルな設計だったから逆に使いやすいものになったんだって。
WEB以前の分散システム
昔はRPCとかCORBA、DCOM等色々な分散システムの考案がされてきたんだけど、他PCに関数を呼び出しをさせたりシリアライズ化したオブジェクトをやりとりしたりしてたんだって。
でもこの方法だと、小さい粒度で関数を頻繁に読む事になったり、PC毎にデータ型やバージョンを揃えなくちゃいけなかったりして、何かと不便だったんだよね。
そういった問題を解決する為に、サーバーとクライアント間のインターフェースをHTTPというシンプルで柔軟なプロトコルが出来上がっていったんだって。
WEBの考え方の変化
HTTPって元々はHTMLを転送する為のプロトコルだったんだけど、わざわざ送信する物はHTMLに限定しなくてもいいよねっていう考え方が広まってきたんだってさ。例えば、microformatsやRSS、Jsonとかね。
そんなこんなでWebの用途が増えてきた結果、Webをプログラムから操作可能にするWebAPIを作りたい動きが広まってきたんだって。
SOAP vs REST
SOAPはWebで必要な技術をたくさん標準化しようとして複雑化していってしまったんだけど、RESTはネットワーク上のリソースを一意なURLだけで表現して、そこにあるリソース(JsonやXML等)を取ってくるだけの非常にシンプルな方式なんだって。
例によってSimple is bestな世の中に合ったRESTが普及していったんだってさ。
まとめ
要はSimple is best!!!
リンクの仕組みに対して余計な要素を出来るだけ入れない事がベストプラクティスで、一意に定めたリソースにアクセス出来るって所がやっぱつえーんやなってなった。リソースの場所さえ決まれば、そこにあるリソースがどういう形式でも引っ張ってこれる方が、クライアントサーバー間でやれる事が増えそうだもんね!
飽くまでもリソース自体のやりとりで完結させる事で、分散処理の仕組みも見えやすくなって良きだね!
RESTについて
リソースについて
WEB上にあるあらゆる情報をリソースと呼び、それぞれ一意なURIでアクセスできる様になってる。URIは階層化された文字列なので、プログラムでの処理が容易だよ。やったね!
RESTってどんなアーキテクチャスタイル?
RESTはクライアント/サーバのアーキテクチャスタイルに色々なアーキテクチャスタイルをのっけて制約を追加した感じになってるんだって。
- クライアント/サーバ
クライアントがサーバにリクエストを送って、サーバーがそれにレスポンスを返すスタイル。
クライアントとサーバーで処理を分散出来るのが良いところ。それぞれで役割を決めて処理させる事で、クライアント側がどんな端末を使っていてもサーバ側は何も知らなくても良い。 - ステートレスサーバ
クライアントの状態をサーバーが管理しないこと。サーバーの実装を簡略化出来るよ! - キャッシュ
クライアントにあるリソースが最新の状態であれば、再度リソースを落として来ずに、ローカルのデータを使いまわして運用する事。ネットワーク処理を短縮して効率的に処理ができるよ! - 統一インターフェース
HTTP通信で出来る事を8つのメソッドで定義されているんだって。
HTTPで出来る事をあえて制限し、通信を使って出来る(やるべき)事のガイドラインを敷く事で、通信におけるやりとりをシンプルに実装出来るんだよ! - 階層化システム
クライアントとサーバー間にロードバランサ(負荷分散)やプロキシ(アクセス制限)を設置したり、サーバーまでに接続する間に階層的に何らかの仕組みを入れる事が出来るんだって。
これらは統一インターフェースによって、同じインターフェースでやりとりできるからこそ実現出来たアーキテクチャスタイルなんだよ! - コードオンデマンド
クライアントで実行する為のプログラムをサーバーからダウンロードしてくる事で、クライアントを後から拡張できる様にするアーキテクチャスタイルだよ!
ただ、これをやりすぎると通信間でのやりとりが段々と不透明になってくるので注意が必要だよ!
これら6つのアーキテクチャスタイルを持っている通信が理想形ではあるんだけど、幾つか排除して柔軟に設計しても問題ないよ!でも、その場合はP2Pとかの別の通信方法が適していないかを考える必要があるんじゃないかなぁ?
RESTの代表的な利点
上記のRESTの仕組みによって、リンクを辿る作業の中でアプリの状態が遷移させられる。この特徴はリソースのURIさえわかれば他のアプリでもリソースを再利用できるぞ!
また、どこかで先述していたネットワーク内で関数やクラスの呼び出しをする仕組みだと、ネットワークアクセスの粒度が小さすぎてオーバーヘッドが大きくなってしまう><。でも、リソースという意味を持った塊のデータであれば、比較的粒度の大きいやりとりで済むので、オーバーヘッドが小さくて済むよね!
また、お互いにRESTに基づいた通信であれば統一インターフェースによって、インターフェースが固定化されているので、サーバーの変更によって互換性が失われにくいね!
まとめ
通信を何につかうべきかをRESTのアーキテクチャスタイルによって示されている事で、REST APIを設計及び運用する際にやるべき事が分かりやすくなった!
飽くまでもやりとりする情報はリソースで、そのリソースによってアプリの状態を変更させるという事が非常にしっくり来た。(要はこのリンクに書いてる事)
第2部 URI
URIとは、同じルールで記述された(統一的に)、リソースを一意に示す名前の事
URIは基本的に下記の様な構成で構築されている。
- URIスキーム:(「http」の部分)
URIが利用するプロトコル(例外はあるっぽい) - ホスト名(「studio.manntera.com」の部分)
インターネット上で必ず一意になる部分。
DNS(Domain Name System)ってのが名前の解決をしてくれる - パス(「/合同誌」の部分)
ホストの中にあるリソースを一意に示すもの
他にもポート番号とかクエリとか色々設定できるよ。
思ったより色々あるので随時ググった方がよさそう。
※URIの実装で気を付ける事
- 相対URIはクライアントと側に不親切だから出来るだけ絶対URIを使うといいよ
- URIに日本語とか入れたい場合はUTF-8の文字コードを使う
URIの設計
ベースとなる思想として、出来るだけ変わらないURI(クールURI)になる様に心がけようね。
URI変わっちゃうとリンク切れたりとかしてそもそものWEBの構造が成り立たなくなっちゃうからね。
- プログラミング言語に依存した拡張子やパスを含めない
- 実装する言語や機能が変わったりするとURLを変更する必要が出てくるよ
- メソッド名やセッションIDを含めない
- コードをリファクタリングするとURL変わっちゃうよ。
- URIはリソースを表現する名詞にする
- URIはリソースを一意に表す名前なので、名詞で表現しようね。動作はHTTPメソッドで指定しようね。
どーしてもURIを変更したい時は?・w・
→リダイレクトしよう!
→古いURIを新しいURIに転送するHTTPの仕組み
URIはクライアントにとって不透明である
- URIをクライアント側で構築するとサーバーと密結合な設計になるので注意しようね。サーバーから提供されたURIを使う様に心がけよう!
- (まんてらさん的には???)
- 友人に相談した感じ、あまりにも難解な生成はやめようねって話?
まとめ
URIがコロコロ変わっちゃうとリンク切れたりクライアント側が実装しなおしたりとかでWEBが成り立たなくなるから避ける様に心がけようね。
また、URIは飽くまでもリソースの在りかを示すものなので、動作指示はHTTPメソッドでやろうね!
第3部 HTTP
HTTPとは、TCP/IPをベースにしたハイパーテキスト(HTMLとか)の転送用プロトコル。でも、実際はコンピューターで使えるデータならなんでも転送できる。
TCP/IPとは何か
ネットワークプロトコルは階層型になっていて、それぞれを抽象化して実装すると下位層の事を気にせずに上位層を実装出来る様になってるよ
アプリケーション層
HTTP部分。
データのやりとりを抽象化したソケットってのを接続、送信、受信、切断等の操作してやりとりする。
トランスポート層
TCP/IPのTCP部分。
データの抜け漏れチェックとかしてデータの到達を保証する。
転送データがどのポートに渡るかを決定することで、そのデータがアプリケーションで使われる所を確定させる。
インターネット層
TCP/IPのIP部分。パケットをやりとりする所。指定したIPアドレスにパケットを送り出すことだけを保証しており、最終的な所まで届くかはしらん。
ネットワークインターフェース層
物理的なコードとかアダプタとか
クライアントとサーバ
クライアントがサーバにリクエストを出して、それに対してサーバがクライアントにレスポンスを出すアーキティクチャスタイル。
HTTPは同期型のプロトコルな為、時間がかかってもレスポンスが返るまで待機する。
リクエストとレスポンス
- リクエスト
- リクエストメッセージ構築→リクエスト送信→レスポンス待機→レスポンス受信→内容解析→処理
- レスポンス
- リクエスト待機→リクエスト受信→リクエスト解析→処理→処理結果取得→レスポンス構築→送信
HTTPメッセージ
リクエスト
- リクエストライン
- メッセージの1行目にHTTPメソッド、ホスト移行の相対パス(若しくは絶対パス)、プロトコルバージョンが記述されている。
- ヘッダ
- 2行目以降に含まれる。メッセージのメタデータ。Host:manntera.comみたいな感じで書かれてる。
- ボディ
- ヘッダの後に続くメッセージ。サーバーに送信したいメインの内容
レスポンス
- ステータスライン
- 1行目に書かれている。プロトコルバージョン、ステータスコード、テキストフレーズから成り立つ。成功した場合は200。失敗した場合はそれに応じたコードとテキストが返ってくる。
- ヘッダ
- リクエストメッセージとおんなじ感じ。Content-Typeとか入る所。
- ボディ
- リクエストメッセージとおんなじ感じ。HTMLとか入る所。
HTTPメッセージの構成要素
- 1行目
- スタートライン
- リクエストとレスポンスで内容が違う
- ヘッダ
- CRLFで改行。空行でヘッダ終了。省略可能
- ボディ
- 省略可能。色々入れれる。
HTTPのステートレス性
サーバーがクライアントの状態を記憶していると、クライアントの数が増えた時に大変な事になる。そのため、クライアント側はメッセージが冗長になるのを代償に、クライアントの状態も含めて処理に必要な全ての情報を伝えながらやりとりをしていく。
ステートレスの欠点として…
- 毎回処理に必要な情報を全て送信する為データ量が多くなる。
- ユーザー認証等データーベースにアクセスするサーバーにとって重い処理を何回も行う必要がある。
- 通信エラーが発生した時、リクエストが正しく処理されたかが分からない場合、バグの温床になる。
HTTPメソッド
GET,POST,PUT,DELETE,HEAD,OPTIONS,TRACE,CONNECTの8種類のメソッドがある。
TRACE,CONNECTはほとんど使われていないらしい。
Discussion