インターネットの仕組み
インターネットが、レイヤー化されたプロトコルとインフラを通じてクライアントとサーバーをどのようにつなぐのかについて、メンタルモデルを構築する
全体像: リクエストのライフサイクル
Request travels down.
ユーザーの意図が形成される
- インターネットのリクエストライフサイクルは、専門化された複数のレイヤーが順番に連携する協調的なシーケンスです。
- 各レイヤーは異なるシステム上の問題を解決し、次のレイヤーへ責任を引き継ぎます。
- 1つの操作に見えるものは、実際には複数の抽象化をまたいで実行される構造化されたパイプラインです。
詳細
ブラウザ → DNS → TCP → HTTP → サーバー → データベース → レスポンス → レンダリング
高いレベルで見ると、Webリクエストは単一の操作ではなく、複数のシステムが連携するチェーンです。各ステップは、宛先の特定、通信の確立、リクエストの定義、ロジックの処理、データの取得、結果の返却といった、1つの特定の問題を解決するために存在します。
DNSは 「このサービスはどこにあるのか?」 に答え、TCPは 「どうすれば信頼性高く通信できるのか?」 に答え、HTTPは 「何が正確に要求されているのか?」 に答えます。サーバーとデータベースは 「システムは何を計算して返すべきか?」 に答えます。
これらのレイヤーは独立して動作しますが、順番に協調して動きます。システム全体を理解している単一のコンポーネントはなく、それぞれが自分の役割を果たして次へ制御を渡します。
ユーザーには一瞬で起きているように見えることも、実際にはミリ秒単位で実行される抽象化の構造化されたパイプラインです。
トリガー: URLを入力する
人間は名前を入力します。ネットワークには数値のルーティングIDが必要です。
- URLは、直接のネットワークアドレスではなく、ユーザー向けのラベルです。
- ブラウザはドメインを抽出し、解決のために準備します。
- 通信を開始する前に、ドメインをIPアドレスに変換する必要があります。
詳細
ユーザーがURLを入力すると、ブラウザは単に「ページを開く」だけではありません。まず入力を解析して、プロトコル(HTTPSなど)、ドメイン名、要求されたパスを特定します。
コンピュータは example.com のようなドメイン名を使ってトラフィックをルーティングできません。ネットワークは、数値の識別子であるIPアドレスで動作します。
ブラウザはローカルキャッシュを確認し、そのドメインのIPアドレスをすでに知っているかどうかを調べます。知らない場合は、名前をルーティング可能なIPアドレスに解決するためにDNSルックアップ処理を開始します。
この変換ステップが完了して初めて、システムは接続の確立に進めます。
名前からIPへ: DNS解決
DNSは、階層的で世界中に分散された検索システムを通じて、人間が読めるドメイン名をIPアドレスに変換します。
キャッシュヒット: 即時。 キャッシュミス: DNS階層を完全にたどる。
- DNSは、Webサイト名を、コンピュータが通信に使う数値のIPアドレスに変換します。
- 検索は、正しいアドレスが見つかるまで、さまざまなDNSサーバーを順番にたどって進みます。
詳細
DNSは、インターネット向けの分散ディレクトリとして設計されています。1つの中央データベースに依存するのではなく、責任を複数のサーバーレイヤーに分散することで、世界規模の利用を支えています。
ドメインがローカルでまだ知られていない場合、再帰リゾルバが検索を開始します。まずルートサーバーに問い合わせ、そこから .com や .org などの正しいトップレベルドメイン(TLD)サーバーの場所を案内されます。次にTLDサーバーが、その特定ドメインの権威ネームサーバーへリゾルバを誘導します。
権威サーバーが最終的なIPアドレスを返します。そのアドレスはクライアントに返され、ブラウザは次に進んで正しい宛先へのネットワーク接続を確立できます。
この階層的な設計により、DNSは整理され、拡張性が高く、毎日何十億もの検索を支えられるようになっています。
接続: TCPハンドシェイク
信頼できる通信は、両者が会話の進め方に合意して初めて始まります。
クライアント
サーバー
クライアント: 同期しましょう!
- TCPは、データが信頼性高く、正しい順序で届くことを保証します。
- データを送信する前に、両者は3段階のハンドシェイクを行います。
- このハンドシェイクは、準備完了を確認し、シーケンス番号を同期します。
詳細
TCPは、すぐにアプリケーションデータの送信を開始するわけではありません。まず、SYN → SYN-ACK → ACK という3段階のプロセスで接続を確立します。
クライアントはまず、接続を要求するためにSYN(synchronize)メッセージを送信します。サーバーはSYN-ACKで応答し、要求を確認するとともに、自身の開始シーケンス番号を共有します。その後、クライアントはACKを送信して受信を確認します。この時点で、両者は初期シーケンス番号に合意し、相手側が準備完了であることを認識しています。
このやり取りによって、信頼性の高い配信の基盤が整います。TCPはシーケンス番号を追跡し、失われたパケットを検出し、不足しているデータを再送し、ネットワーク状況に応じて送信速度を調整します。
この調整のステップが完了して初めて、実際のアプリケーションデータが流れ始めます。
アプリケーション層: HTTP
HTTP は、クライアントがリソースをどのように要求し、サーバーが構造化された request-response プロトコルを通じてどのように応答するかを定義します。
- HTTP は、ブラウザとサーバーの両方が従う共通言語を定義します。
- リソースの要求方法とレスポンスの形式を標準化します。
- 生のネットワークデータを、「このページを取得する」や「このフォームを送信する」といった意味のある操作に変換します。
詳細
TCP はバイトの信頼性の高い配送を保証しますが、それらのバイトが何を意味するかは定義しません。HTTP は TCP の上位にあり、通信に構造と意味を与えます。クライアントが何かを要求する方法と、サーバーがどのように応答するかを定義します。
HTTP request には、GET や POST などの method、メタデータを記述する headers、そして必要に応じてデータを含む body が含まれます。サーバーは status code、headers、そして要求された content を返します。両者が同じルールに従うため、メッセージを一貫して解釈できます。
インターネットは共有システムであるため、HTTP は不可欠です。メッセージの構造と意図を定義する共通プロトコルがなければ、ブラウザとサーバーは互いを理解できません。HTTP は Web のための共通言語を作ります。
HTTP が定義するのは、何が要求され、何が返されるか であり、データがネットワーク上を物理的にどのように移動するかではありません。
サーバー内部
サーバーは、オペレーティングシステムがハードウェア資源を管理し、アプリケーションコードがリクエストを処理して応答することで動作します。
受信リクエスト
OSがCPU + メモリを割り当てる → アプリがロジックを実行する
送信済みレスポンス
- クライアントからのリクエストが届き、オペレーティングシステムを通じてサーバープログラムに渡されます。
- オペレーティングシステムは、そのリクエストを処理するために CPU 時間、メモリ、ネットワークアクセスを割り当てます。
- サーバーアプリケーションがロジックを実行し、返送するレスポンスを生成します。
詳細
データがマシンに届いても、自動的に「実行」されるわけではありません。オペレーティングシステムはネットワークデータを受け取り、ソケットを使って正しいプロセスへ振り分けます。これが、リクエストがサーバープログラムに届く仕組みです。
その後、OS が必要なリソースを管理します。サーバーが実行できるように CPU 時間をスケジューリングし、処理用のメモリを割り当て、ファイルやデータベースへのアクセスを制御します。オペレーティングシステムがこれらのリソースを調整しなければ、複数のリクエストを安全かつ効率的に処理することはできません。
リクエストがサーバープロセスに入ると、アプリケーションロジックが処理を引き継ぎます。HTTP メッセージを解釈し、必要な計算やデータベース検索を行い、レスポンスを構築します。
オペレーティングシステムは実行を可能にします。サーバーアプリケーションは振る舞いを定義します。
データベースと永続化
データベースは、アプリケーションのデータを長期間にわたって保存し、整理し、信頼性高く取得するために設計されたシステムです。
| ID | 名前 | 役割 |
|---|---|---|
| 21 | Alice | User |
| 22 | Brian | Admin |
| 23 | Cathy | User |
| 24 | Daniel | User |
| 25 | Eva | Admin |
- データベースは、単一のプログラムの実行を超えてデータを永続的に保存するために存在します。
- 情報を整理することで、効率的に検索・更新できるようにします。
詳細
アプリケーションは、ユーザーアカウント、投稿、トランザクション、ログ、設定などのデータを常に生成します。このデータがメモリ上にしか存在しない場合、プログラムが再起動するたびに消えてしまいます。データベースは、ディスクや分散システム上に永続的な保存領域を提供することで、この問題を解決します。
しかし、保存するだけでは十分ではありません。データは構造化され、クエリ可能である必要があります。データベースは情報をテーブルやコレクションに整理し、アプリケーションがすべてを手動で走査しなくても特定のレコードを取得できるクエリ言語を提供します。
パフォーマンスを向上させるために、データベースはインデックスを使用します。インデックスは、検索用のマップのように機能する特殊なデータ構造です。すべての行を確認する代わりに、エンジンは関連するエントリへ直接移動できます。
データベースが重要なのは、現代のアプリケーションには永続的な状態が必要だからです。データベースがなければ、すべてのリクエストは独立して処理され、過去の操作を記憶できません。
パフォーマンス層: キャッシュとCDN
現代のシステムは、毎回再計算する代わりに、頻繁に要求されるコンテンツをユーザーの近くに保存することで速度を向上させます。
- キャッシュは、保存済みのレスポンスを返すことで、繰り返しの計算を避けます。
- CDNはコンテンツを地理的に分散して配信し、レイテンシとオリジンの負荷を減らします。
詳細
ユーザーが同じリソースを複数回要求する場合、毎回ゼロから再計算するのは非効率です。キャッシュはレスポンスのコピーを保存することでこれを解決し、以後のリクエストをデータベースやアプリケーションロジックに再度アクセスせずに即座に返せるようにします。
キャッシュは複数の層に存在します。ブラウザ内、サーバー上、そしてネットワークのエッジです。Content Delivery Network (CDN) は、この考え方を世界規模に拡張し、コンテンツを地理的に分散したデータセンターへ配信します。常にオリジンサーバーへ問い合わせる代わりに、ユーザーは最も近いエッジロケーションへルーティングされます。
物理的な距離を短くするとネットワークレイテンシが下がり、繰り返しの計算を減らすとサーバー負荷が下がります。これらの最適化を組み合わせることで、スケール時のレスポンスタイムは大幅に改善されます。
ただし、キャッシュされたデータは古くなる可能性があるため、システムは速度とデータの新しさのバランスを取る必要があります。
障害ポイント
レイヤー化されたシステムでは、経路上のどのコンポーネントでも障害が発生する可能性があり、全体の体験はシステムがそれらの障害をどれだけうまく処理できるかに左右されます。
DNS
TCP
サーバー
データベース
- リクエストのライフサイクルにある各レイヤーは、それぞれ独立して失敗する可能性があります。
- あるコンポーネントの障害によって、リクエスト全体が完了できなくなることがあります。
- 信頼性の高いシステムは、部分的な障害を予測し、回復できるように設計されています。
詳細
インターネットのリクエストライフサイクルは、DNS、トランスポート、サーバー、データベースにまたがるため、どの段階でも問題が発生する可能性があります。DNS がドメインを解決できなければ、接続は始まりません。ネットワークがパケットを落としたり、TCP 接続が切断されたりすると、通信は中断されます。
リクエストがサーバーに届いた後でも、障害は起こりえます。サーバープロセスがクラッシュしたり、メモリ不足になったり、データベースへの接続に失敗したりすることがあります。遅い、または応答しないデータベースは、レスポンス全体を遅延させる可能性があります。
分散システムが一度にすべて失敗することはめったにありません。代わりに、1つのリージョン、1つのインスタンス、または1つの依存先が一度に部分的に失敗します。レジリエントなシステムを設計するには、複数のレイヤーにわたって冗長性、ヘルスチェック、リトライ、フォールバック機構を追加する必要があります。
障害がどこで発生しうるかを理解することは、実際のシステムがどのように動作するかを理解するうえで不可欠です。
質問セクション
1 / 5