Web Server
概要
Webサーバはソフトウェアの種類の1つ。HTTPに則りブラウザに対して表示を提供する。
Memo
ProxyPassとProxyReverse
リバースプロキシするときに、よくProxyPassとProxyReverseを設定する。これらの違いはなにか。ProxyPassは文字通りリバースプロキシする設定。ProxyReverseは、リバースプロキシ先でのリダイレクトが発生したときに書き換える指定。
リダイレクトがあるときProxyReverseを設定していないと、バックエンドサーバから見たフロントエンドへのアドレスをLocationヘッダに設定する。当然ブラウザからは開けないので404エラーになる。
わかりやすい解説。
JWT認証
JWT(JSON Web Token)はトークンの1つ。
- 【Rails×JWT】ログイン認証解説とJWT初期設定ファイルの作成 - 独学プログラマ
- ブラウザ: ログインする
- サーバ: ログイン情報と一致するユーザを検索。存在すればJWTを発行し、Cookieに保存する
- サーバ: ブラウザにJSONを返す。有効期限とユーザオブジェクトを返す。JWTはそのものは返さない
- ブラウザ: JSONを保存する。保存したユーザオブジェクトをログイン中のユーザとして扱う。保持されている有効期限を、ログイン状態を維持するかの判定に使う。
ルート以外アクセスできないとき
だいたいの場合、index.jsやindex.phpを見に行く設定をしてない。パスがWebサーバの機能の1つである静的ファイルの位置の指定ではなく、indexファイルへ渡されるパラメータとして扱われる必要がある。
Nginxのアーキテクチャを理解する - Qiita
アーキテクチャの説明。
- 並行(concurrent)
- 複数の仕事を切り替えることにより同時に実行する
- 並列(parallel)
- 複数の仕事を同時に実行すること
- 並列は並行を包含している
- マルチプロセス
- 複数のプロセスを並列処理する
- クライアントからの接続ごとにプロセスをフォークして処理する
- シングルプロセス
- 1つのプロセスでのプログラム実行
- プロセスは1つなので、並行処理
- マルチスレッド
- 複数のスレッドを並列処理すること
- 1プロセスの中で各スレッドの並列処理を行うことができる
- クライアントからの接続ごとにスレッドを生成して処理する
- マルチプロセスモデルに比べメモリ空間の切り替えがない分、メモリ消費量やコンテキストスイッチのオーバーヘッドが少なくなる
- シングルスレッド
- 並列処理ではなく、単一の命令の流れを逐次的に実行していく並行処理を挿す
- Apache
- preforkモデル
- マルチプロセスモデル
- スレッドを使わず、先行してforkを行う
- リクエストとプロセスが1対1対応で処理する
- 子プロセスが停止しても他のプロセスには影響を及ぼすことがなく通信を継続できる
- Linuxは起動できるプロセスの数が制限されているので、C10K問題が起こる
- workerモデル
- マルチプロセスとマルチスレッドのハイブリッド型モデル
- Apacheの子プロセス1つ1つがマルチスレッドで動作し、スレッド1つ1つがクライアントを処理する
- 多くの子プロセスを起動せずにメモリの使用量を減らせる
- preforkモデル
- Nginx
- イベント駆動モデル
- クライアントのアクセスをイベントとして扱い、それをトリガーにプロセス内で処理を行うこと
- 1プロセスは1スレッドしか利用しないので、CPUの数だけプロセスを用意するワーカーモデルが利用される
- Node.jsと同じイベントループ方式 – シングルスレッドでループ処理をまわし、キューに溜まったイベントを処理していく処理方式
- シングルスレッドのプロセスのためメモリ空間の共有が可能
- 同時接続数が増えてもプロセス数やスレッド数は増えないのでC10K問題が起こらない
- メモリ消費量やコンテキストスイッチのオーバーヘッドが小さい
- イベント駆動モデル
- NginxのI/O処理では、イベントループによる非同期なイベント駆動と、IOの多重化によって、workerプロセスにてリクエストが完全に処理されることを待たずに処理を捌くことができる
Reference
アーキテクチャ大全 - kawasima
WEBでありがちな部品がまとめられたページ。
ログ設計指針 - Qiita
ログの設計指針。
開発者が運用を経験すべき一つの理由 | DevelopersIO
ログはその重要性にかかわらず認識されていない。
Archives
DONE webサーバは何をしているか DontKnow
最後のプロジェクト:マルチスレッドのWebサーバを構築する - The Rust Programming Language 日本語版
シンプルなWebサーバを実装し、基本的な仕組みを理解する。
- 接続は、クライアントがサーバに接続し、サーバがレスポンスを生成し、サーバが接続を閉じるというリクエストとレスポンス全体の過程の名前
let response = "HTTP/1.1 200 OK\r\n\r\n";
にするとブラウザwebツールで200 OKが出る。適当な文字列を入れると出ない。入れた文字がそのままページとして表示された- HTTPステータスはレスポンスの先頭行の文字列をパースして得る。文字列はプロトコルとして定義されている
- レスポンスのヘッダ以降は表示される。だからHTMLを入れてレスポンスを返すと、ブラウザで表示できる
- pumaが200を返す部分。https://github.com/kd-collective/puma/blob/e9f09ba1fe6b168bed7fff59d0bdbfd65351cf9d/lib/puma/app/status.rb#L70 当然だが実際の大きなアプリケーションでも、レスポンスを返す部分がある。本質的な部分はシンプルなことがわかる
- パスによる分岐の実態は、アプリケーションを書くうえで直感的に感じる構造とは異なる。サーバ側でパスによる分岐処理があるから表示を分けられる。パス指定されていても、リクエストパスが異なるだけで他は同じ形式のリクエストに過ぎない
スレッドプール
何も工夫がない場合、遅いリクエストを受けた場合ほかのリクエストも同様に待たされることになる。そうならないための仕組みがある。
- スレッドプールは、待機し、タスクを処理する準備のできた大量に生成されたスレッド。プログラムが新しいタスクを受け取ったら、プールのスレッドのどれかをタスクにあてがい、そのスレッドがタスクを処理する
- 最初のスレッドがタスクの処理を完了したら、アイドル状態のスレッドプールに戻り、新しいタスクを処理する準備ができる
- スレッドプールにより平行で接続を処理でき、サーバのスループットを向上させる
- プールのスレッド数は小さい数字に制限し、DOS攻撃から保護する
- スレッドを大量生産するのではなく、プールに固定された数のスレッドを待機させる
ワーカー
標準ライブラリはスレッドを生成する手段として thread::spawn
を提供する。生成されるとすぐにスレッドが実行すべき何らかのコードを得る。スレッドを生成して、後ほど送信するコードを待機してほしい。
- この振る舞いを管理するスレッドと
ThreadPool
に新しいデータ構造を導入する。このデータ構造を Worker とよび、プール実装では一般的な用語 - ログを取ったり、デバッグする際にプールの異なるワーカーを区別できるように、各ワーカーにidも付与する
- workerは作業者という意味。ワーカースレッドが仕事を1つずつ取り、処理する。仕事がなかったらワーカスレッドは新しい仕事が届くまで待つ。
- ワーカースレッドが繰り返し仕事を実行するので、新しいスレッドを実行する必要がない。つまりリソースの消費が少ない
- ワーカースレッドが持っているフィールドは仕事のリクエストを得るためのインスタンスだけで、具体的な仕事内容は知らない
- 『Java言語で学ぶデザインパターン(マルチスレッド編)』まとめ(その10) - Qiitaが参考になった
- ThreadPool > workers > thread