バベルの図書館は完成しない

Extended outer memory module
for my poor native memory.

Posts:
2022/02/13 クラビスの CTO になりました
2020/09/28 gendoc という YAML からドキュメントを生成するコマンドを作った
2020/09/13 ISUCON10 の予選を 7 位で通過した
2019/12/01 Puma の内部構造やアーキテクチャを追う
2019/05/27 Golang の正規表現ライブラリの処理の流れをざっくり掴む
2019/04/29 InnoDB の B+Tree Index について
2019/04/29 InnoDB における index page のデータ構造
2019/04/28 InnoDB はどうやってファイルにデータを保持するのか
2019/01/06 Designing Data-Intensive Applications を読んでいる
2019/01/03 年末年始に読んだ本について、など
2019/01/01 Ruby から ffi を使って Rust を呼ぶ
2018/11/10 ブラウザにおける状態の持ち方
2018/07/01 Rust で web アプリ、 或いは Rust における並列処理
2018/05/14 なぜテストを書くのか
2018/05/13 Rust で wasm 使って lifegame 書いた時のメモ
2018/03/12 qemu で raspbian のエミュレート(環境構築メモ)
2018/03/12 qemu で xv6 のエミュレート(環境構築メモ)
2018/03/03 Ruby の eval をちゃんと知る
2018/02/11 Web のコンセプト
2018/02/03 Rspec のまとめ
2018/02/03 Ruby を関数型っぽく扱う

Web のコンセプト

Goならわかるシステムプログラミング第6回を読んでいて、ネットワーク通信についてあまり理解していないなと思った。

そこでネットワーク通信技術の前提となるwebの考え方(特にREST)、モチベーションなどについて調べてまとめることにする。

その上で、ソケットについても基本をまとめておく。

通信のレイヤとプロトコル

レイヤの名称 代表的なプロトコル
アプリケーション層 HTTP
トランスポート層 TCP / UDP / QUIC
インターネット層 IP
リンク層 Wi-Fi / イーサネット

web の基本概念

情報は全て resource であり、webページは resource の表現( representation )の一つ。

REST のモチベーション

あらゆる情報( resource ) をURLのように階層構造への配置として表現したい。その上で、 resource に対して行いたい操作を抽象化・共通化する(ポリモーフィックな定義)ことで、あらゆる resource に対して共通の文脈から接したい。( resource に応じた個別的なことはなるべく行いたくない。)

すべての resource が RESTful な状態で配置されているとすれば、機械的に処理できる情報が増えるはず。

予め配置がわかっていることで resource 同士のリンクが張れるようになる。

http というプロトコルのモチベーション

REST を前提に、行いたい操作対象の情報の2つの情報によって、クライアントがサーバに対して行いたい行動が一意に定まる(はず…?)。

この2つをクライアントとサーバ間で伝達することを実現するためにできたのが http というプロトコル。

当初のコンセプトができて実際に利用されるようになって以来、 http の仕様は時間の経過と共に複雑化しているが、その間の変化に関しては基本的に 高速化セキュリティ強化 の文脈で説明できる。

http のメソッド

http メソッド 意味
GET resource の取得
POST resource の作成
PUT resource の作成、置換
PATCH resource の部分置換
DELETE resource の削除

※ 他にも HEAD とか OPTIONS とか TRACE とか LINK とか UNLINK とかあるみたい

POST と PUT と PATCH の違い

POST はクライアント側で resource の親 resource を指定して更新を行う(サーバ側で resource 名が割り振られる): 行うごとに結果としての resource の状態は変化する

PUT はクライアント側で resource を指定して更新を行う: 何度行っても結果としての resource の状態は同じになる

PATCH はクライアント側で resource を指定して部分的な更新を行う( PUT に似てる)

REST の発展系としての HATEOAS の考え方

REST は resource の位置と resource に対するメソッドの適用ですべての情報との関わり合いを定義していた。

しかしこれだと、既知の resource に対する追加的な resource が見えないことがあった。

(例: /piyo/user/1 に対しての /piyo/user/1/role は、 /piyo/user/1 という resource のみからでは知り得ない。(もちろんリンクしてあれば別だけど))

HATEOAS の考え方ではこの問題を解決するために以下のようなアイデアを用いている。

HATEOAS のアイデア

一つのAPIまたはリソースに対してはエントリポイントは単一であるべきで、リソースの表現はそのリソース上で実行できるすべてのアクションを含むべきである

ある HATEOAS な API による例

REST の場合

{
  "user": {
    "first_name": "おでん君",
    "last_name": "ハイパー",
    "age": 65536
  }
}

HATEOAS の場合

{
  "user": {
    "first_name": "おでん君",
    "last_name": "ハイパー",
    "age": 65536,
    "links": [
      {
        "rel": "self",
        "href": "https://piyofunction.com/piyo/user/1"
      },
      {
        "rel": "roles",
        "href": "https://piyofunction.com/piyo/user/1/roles"
      }
    ]
  }
}

この例からわかるように HATEOAS では追加的な情報として、単一エンドポイントとしてのselfと実行できるアクションとしてのrolesがレスポンスに含まれている

ソケット

http によるアプリケーション層での通信が、下位レイヤであるトランスポート層を利用する際の API として存在するのがソケット。

ソケットは OS の提供するプロセス間通信( IPC )の一種。他にはシグナル、メッセージキュー、パイプ、共有メモリなどの IPC がある。

ソケットとその他の IPC の差として、ソケットはアドレスとポート番号が与えられることで外部のコンピュータとも通信が行える点が挙げられる。

ソケットを用いた通信

サーバ側はソケットを開いて待ち受け、クライアント側は開いているソケットに接続する

Go言語ではサーバ側のソケット開通が Listen メソッド、クライアント側のソケットへの接続が Dial メソッドとして定義されている。( API の命名ルールとして決まっている。)

具体的な通信の手順は以下

参考:

2018/02/11 12:00
tags: web
This site is maintained by furuhama yusuke.
from 2018.02 -