目次
1. [ネットワーク基礎: OSI & TCP/IP](#1-ネットワーク基礎)
2. [ソケットプログラミング: asyncio & aiohttp](#2-ソケットプログラミング)
3. [サービスメッシュ: Istio & Envoy](#3-サービスメッシュ)
4. [ネットワークセキュリティ: TLS & Zero Trust](#4-ネットワークセキュリティ)
5. [CDN & エッジコンピューティング](#5-cdn--エッジコンピューティング)
6. [AIサービングネットワーク: gRPC & SSE](#6-aiサービングネットワーク)
7. [パケット解析の実践](#7-パケット解析の実践)
8. [クイズ](#クイズ)
1. ネットワーク基礎
OSI 7レイヤーモデル
OSI(Open Systems Interconnection)モデルは、ネットワーク通信を7つの層に抽象化した参照モデルです。
| 層 | 名称 | プロトコル例 | PDU |
| --- | ------------------ | -------------------- | ------- |
| 7 | アプリケーション | HTTP, DNS, SMTP | Message |
| 6 | プレゼンテーション | TLS, JPEG, ASCII | Message |
| 5 | セッション | NetBIOS, RPC | Message |
| 4 | トランスポート | TCP, UDP | Segment |
| 3 | ネットワーク | IP, ICMP | Packet |
| 2 | データリンク | Ethernet, 802.11 | Frame |
| 1 | 物理 | ケーブル、光ファイバ | Bits |
TCP/IPスタック
実際のインターネットは、OSIより単純化された4層のTCP/IPモデルを使用します。
- **アプリケーション層**: HTTP/2, HTTP/3, DNS, TLS
- **トランスポート層**: TCP(信頼性), UDP(速度)
- **インターネット層**: IPv4, IPv6, ICMP
- **リンク層**: Ethernet, Wi-Fi
HTTP/2 と HTTP/3 の違い
HTTP/1.1では、1つの接続で同時に1つのリクエストしか処理できず、Head-of-Line (HOL) ブロッキングが発生します。
**HTTP/2 の改善点:**
- マルチプレキシング: 1つのTCP接続で複数ストリームを同時処理
- ヘッダー圧縮: HPACKアルゴリズムで重複ヘッダーを削除
- サーバープッシュ: クライアントのリクエストなしにリソースを先制送信
- バイナリフレーミング: テキストの代わりにバイナリフレームを使用
**HTTP/3 & QUIC:**
HTTP/3はTCPの代わりにQUIC(UDPベース)上で動作し、TCPレベルのHOLブロッキングも解消します。
HTTP/1.1: [Req1] → [Res1] → [Req2] → [Res2] (逐次処理)
HTTP/2: [Req1, Req2, Req3] → [Res1, Res2, Res3] (多重化、単一TCP)
HTTP/3: [Req1, Req2, Req3] → [Res1, Res2, Res3] (多重化、独立QUICストリーム)
DNS の動作原理
`api.example.com` を解決する際のフロー:
1. ブラウザキャッシュの確認
2. OSキャッシュの確認 (`/etc/hosts`)
3. 再帰リゾルバ(ISP DNS)へのクエリ
4. ルートNS → `.com` TLD NS → `example.com` 権威NSへの階層的解決
5. Aレコード(IPv4)またはAAAAレコード(IPv6)を返す
TLS 1.3 ハンドシェイク
TLS 1.3 は往復回数を削減し、新規接続では1-RTT、セッション再開では0-RTTで確立します。
Client Server
|--- ClientHello (鍵共有) ------>|
|<-- ServerHello + Certificate --|
|<-- + EncryptedExtensions ------|
|--- Finished ------------------->|
|<-> 暗号化されたデータ交換 <------>|
2. ソケットプログラミング
Python asyncio TCPサーバー
async def handle_client(reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
addr = writer.get_extra_info('peername')
print(f"接続: {addr}")
try:
while True:
data = await reader.read(1024)
if not data:
break
message = data.decode('utf-8').strip()
print(f"受信: {message} from {addr}")
エコー応答
response = f"Echo: {message}\n"
writer.write(response.encode('utf-8'))
await writer.drain()
except asyncio.IncompleteReadError:
pass
finally:
print(f"切断: {addr}")
writer.close()
await writer.wait_closed()
async def main():
server = await asyncio.start_server(
handle_client, '0.0.0.0', 8888
)
addr = server.sockets[0].getsockname()
print(f"サーバー開始: {addr}")
async with server:
await server.serve_forever()
if __name__ == '__main__':
asyncio.run(main())
aiohttp を使った非同期HTTPクライアント
from typing import List
async def fetch_url(session: aiohttp.ClientSession, url: str) -> dict:
async with session.get(url, timeout=aiohttp.ClientTimeout(total=10)) as response:
return {
'url': url,
'status': response.status,
'body': await response.text()
}
async def fetch_all(urls: List[str]) -> List[dict]:
connector = aiohttp.TCPConnector(
limit=100, # 最大同時接続数
limit_per_host=10, # ホストあたりの最大接続数
keepalive_timeout=30
)
async with aiohttp.ClientSession(connector=connector) as session:
tasks = [fetch_url(session, url) for url in urls]
return await asyncio.gather(*tasks, return_exceptions=True)
実行
urls = [f"https://httpbin.org/get?id={i}" for i in range(20)]
results = asyncio.run(fetch_all(urls))
gRPC vs REST の比較
| 項目 | gRPC | REST |
| -------------------- | ---------------------------- | ---------------------------- |
| プロトコル | HTTP/2 | HTTP/1.1 または HTTP/2 |
| シリアライゼーション | Protocol Buffers(バイナリ) | JSON(テキスト) |
| ストリーミング | 双方向ストリーミング対応 | 限定的(SSE・WebSocket別途) |
| 型安全性 | 強い型付け(.protoスキーマ) | 弱い型付け |
| レイテンシ | 低い | 相対的に高い |
| ブラウザサポート | grpc-web が必要 | ネイティブ対応 |
3. サービスメッシュ
Istio アーキテクチャ
IstioはサイドカーパターンでEnvoyプロキシを各Podに注入し、サービス間通信を制御します。
- **コントロールプレーン (Istiod)**: 設定管理、証明書発行、トラフィックポリシー配布
- **データプレーン (Envoy Sidecar)**: 実際のトラフィック処理、メトリクス収集、mTLS適用
VirtualService 設定例
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ml-inference-vs
namespace: production
spec:
hosts:
- ml-inference-svc
http:
- match:
- headers:
x-model-version:
exact: 'v2'
route:
- destination:
host: ml-inference-svc
subset: v2
weight: 100
- route:
- destination:
host: ml-inference-svc
subset: v1
weight: 90
- destination:
host: ml-inference-svc
subset: v2
weight: 10
ロードバランシングアルゴリズム
- **ラウンドロビン**: 順番にリクエストを分散(デフォルト)
- **最小接続数**: アクティブ接続が最も少ないサーバーを選択
- **重み付きラウンドロビン**: 重みに基づいてリクエストを分散
- **IPハッシュ**: クライアントIPで特定サーバーに固定(セッション維持)
- **一貫性ハッシュ**: サーバー追加・削除時の再分散を最小化(分散キャッシュ向け)
サービスディスカバリ
Kubernetes環境ではCoreDNSがサービスディスカバリを担当します。
`service-name.namespace.svc.cluster.local` の形式でサービスにアクセスします。
4. ネットワークセキュリティ
TLS 証明書チェーン
ルートCA(ブラウザ/OSに組み込み済み)
└── 中間CA
└── リーフ証明書(実際のサーバー証明書)
各証明書は上位CAの秘密鍵で署名され、信頼チェーンを形成します。
mTLS(Mutual TLS)
通常のTLSはサーバーのみが証明書を提供します。mTLSはクライアントも証明書を提示し、双方向認証を行います。
通常TLS: Client → [サーバー証明書を検証] → Server
mTLS: Client ↔ [双方向証明書を検証] ↔ Server
サービスメッシュでは、mTLSはサイドカープロキシが自動的に処理し、アプリケーションコードの変更なしにサービス間通信を保護します。
Nginx TLS 設定
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/private/server.key;
TLS 1.2以上のみ許可
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
HSTS(1年間)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
OCSPステープリング
ssl_stapling on;
ssl_stapling_verify on;
location /api/ {
proxy_pass http://backend_pool;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Zero Trust アーキテクチャ
Zero Trust の核心原則: 「決して信頼せず、常に検証せよ(Never Trust, Always Verify)」
- **IDベースのアクセス制御**: IPアドレスではなくユーザー/サービスIDで認証
- **最小権限の原則**: 必要なリソースへのアクセスのみ許可
- **継続的な検証**: セッション中も継続的に信頼レベルを評価
- **マイクロセグメンテーション**: ネットワークを小さなゾーンに分割し横断移動を阻止
JWT & OAuth 2.0
JWT(JSON Web Token)は3つの部分で構成されます: `Header.Payload.Signature`
OAuth 2.0 認可コードフロー:
1. クライアントがユーザーを認可サーバーにリダイレクト
2. ユーザー認証後、認可コードを発行
3. バックエンドでコードをアクセストークンに交換
4. アクセストークンでリソースサーバーのAPIを呼び出す
5. CDN & エッジコンピューティング
CDN の仕組み
CDN(Content Delivery Network)は世界中のPoP(Points of Presence)にコンテンツをキャッシュし、レイテンシを削減します。
キャッシュ戦略:
- **Cache-Control: max-age=86400**: ブラウザとCDNで1日キャッシュ
- **Cache-Control: no-cache**: 常にオリジンサーバーに再検証
- **ETag / Last-Modified**: 条件付きリクエストで変更有無を確認
Cloudflare Workers の例
export default {
async fetch(request, env) {
const url = new URL(request.url)
// エッジでAI推論をルーティング
if (url.pathname.startsWith('/inference/')) {
const modelId = url.searchParams.get('model') || 'default'
// 最も近いGPUクラスターにルーティング
const region = request.cf.region
const backendUrl = selectBackend(region, modelId)
return fetch(backendUrl, {
method: request.method,
headers: request.headers,
body: request.body,
})
}
// 静的アセットのキャッシュ
const cache = caches.default
const cachedResponse = await cache.match(request)
if (cachedResponse) return cachedResponse
const response = await fetch(request)
if (response.status === 200) {
const responseToCache = response.clone()
await cache.put(request, responseToCache)
}
return response
},
}
6. AIサービングネットワーク
gRPC を使ったMLモデルサービング
Protocol Buffers 定義:
syntax = "proto3";
package inference;
service InferenceService {
rpc Predict(PredictRequest) returns (PredictResponse);
rpc StreamPredict(PredictRequest) returns (stream PredictResponse);
}
message PredictRequest {
string model_name = 1;
repeated float input_data = 2;
map<string, string> metadata = 3;
}
message PredictResponse {
repeated float output_data = 1;
float confidence = 2;
int64 latency_ms = 3;
}
Python gRPC サーバー:
from concurrent import futures
class InferenceServicer(inference_pb2_grpc.InferenceServiceServicer):
def Predict(self, request, context):
start = time.time()
input_array = np.array(request.input_data)
実際のモデル推論(例示)
output = input_array * 2.0
latency = int((time.time() - start) * 1000)
return inference_pb2.PredictResponse(
output_data=output.tolist(),
confidence=0.95,
latency_ms=latency
)
def StreamPredict(self, request, context):
ストリーミング応答(LLMトークン生成などに活用)
tokens = ["こんにちは", "!", " gRPC", "ストリーミング", "です。"]
for token in tokens:
yield inference_pb2.PredictResponse(
output_data=[float(ord(c)) for c in token],
confidence=0.9,
latency_ms=10
)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
inference_pb2_grpc.add_InferenceServiceServicer_to_server(
InferenceServicer(), server
)
server.add_insecure_port('[::]:50051')
server.start()
print("gRPCサーバー起動: ポート50051")
server.wait_for_termination()
SSE を使った LLM リアルタイムストリーミング
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
async def llm_token_generator(prompt: str):
"""LLMトークンをSSE形式でストリーミング"""
本番環境ではLLMライブラリを使用
tokens = prompt.split() + ["[完了]"]
for i, token in enumerate(tokens):
data = json.dumps({"token": token, "index": i})
yield f"data: {data}\n\n"
await asyncio.sleep(0.05) # トークン生成のシミュレーション
yield "data: [DONE]\n\n"
@app.get("/stream")
async def stream_llm(prompt: str = "こんにちは"):
return StreamingResponse(
llm_token_generator(prompt),
media_type="text/event-stream",
headers={
"Cache-Control": "no-cache",
"X-Accel-Buffering": "no", # Nginxバッファリングを無効化
}
)
7. パケット解析の実践
tcpdump の基本コマンド
特定インターフェースでHTTPトラフィックをキャプチャ
sudo tcpdump -i eth0 -w capture.pcap port 80 or port 443
TCPハンドシェイクのみフィルタリング(SYNパケット)
sudo tcpdump -i any 'tcp[tcpflags] & tcp-syn != 0'
特定ホストとの通信を監視
sudo tcpdump -i eth0 host 10.0.0.1 -n
DNSクエリの監視
sudo tcpdump -i any udp port 53 -v
gRPC(HTTP/2)トラフィックのキャプチャ
sudo tcpdump -i eth0 port 50051 -w grpc_trace.pcap
curl を使ったネットワークデバッグ
TLS証明書情報の確認
curl -vI https://api.example.com 2>&1 | grep -A 20 "SSL connection"
HTTP/2の使用確認
curl --http2 -I https://api.example.com
レスポンス時間の詳細測定
curl -o /dev/null -s -w \
"DNS: %{time_namelookup}s\nTCP: %{time_connect}s\nTLS: %{time_appconnect}s\nTotal: %{time_total}s\n" \
https://api.example.com
gRPCエンドポイントのテスト(grpcurl)
grpcurl -plaintext localhost:50051 list
grpcurl -plaintext -d '{"model_name": "bert", "input_data": [1.0, 2.0]}' \
localhost:50051 inference.InferenceService/Predict
ネットワーク性能指標
- **RTT(ラウンドトリップタイム)**: パケットの往復時間、`ping` で計測
- **スループット**: 単位時間あたりの転送データ量、`iperf3` で計測
- **パケットロス**: 損失率、不安定なUDP環境で重要
- **ジッター**: RTTの変動、リアルタイムストリーミングで重要
ネットワーク帯域幅の測定
iperf3 -s # サーバー
iperf3 -c server_ip -t 30 -P 4 # クライアント(4並列ストリーム)
クイズ
**答え**:
3ウェイハンドシェイク(接続確立):
1. Client → Server: SYN (seq=x)
2. Server → Client: SYN-ACK (seq=y, ack=x+1)
3. Client → Server: ACK (ack=y+1)
4ウェイ終了(接続切断):
1. Client → Server: FIN
2. Server → Client: ACK
3. Server → Client: FIN
4. Client → Server: ACK(TIME_WAIT状態後に完全終了)
**解説**: 終了が4段階になる理由は、サーバーがFINを受け取った後も送信中のデータがある場合があるためです。クライアントはACK送信後にTIME_WAIT状態(2MSL期間)に入り、遅延パケットに対処します。
**答え**: HTTP/2は1つのTCP接続上で複数のストリームを同時に送受信します。各ストリームは独立したIDを持ち、あるストリームの処理が遅延しても他のストリームには影響しません。
**解説**: HTTP/1.1はパイプライニングをサポートしますが、レスポンスはリクエスト順に受け取る必要があるため、先頭のレスポンスが遅いと後続もすべてブロックされます(HOLブロッキング)。HTTP/2はフレーム単位でインターリービングすることでこの問題をアプリケーション層で解決します。ただし、TCPレベルのHOLブロッキングはHTTP/3(QUIC)によって完全に解消されます。
**答え**: 通常のTLSはサーバーの証明書のみを検証しますが、mTLS(Mutual TLS)はクライアントも証明書を提示し、双方向認証を行います。
**解説**: Istioなどのサービスメッシュでは、mTLSはサイドカープロキシ(Envoy)が透過的に処理します。各サービスはSPIFFE IDを持つX.509証明書を発行され、サービス間通信はすべてアプリケーションコードの変更なしに相互認証・暗号化されます。これにより、内部ネットワーク上でも盗聴、なりすまし、中間者攻撃を防ぐことができます。
**答え**: gRPCはProtocol Buffersによるバイナリシリアライゼーション、HTTP/2の多重化、双方向ストリーミングのサポートにより、ML推論ワークロードに最適化されています。
**解説**: 大きなテンソルデータの転送時、Protocol BuffersはJSONと比較して3〜5倍小さいペイロードを生成します。サーバーストリーミングにより、LLMが生成したトークンをリアルタイムにクライアントへ配信できます。また、.protoスキーマでAPIコントラクトが厳密に定義されるため、MLパイプライン統合時の型安全性が保証されます。
**答え**: 主な戦略としてTTLベースの期限切れ、バージョン付きURL、APIによる即時無効化、サロゲートキー(タグ)ベースの無効化があります。
**解説**:
- **TTLベース**: 実装が簡単だが、期限切れまで古いコンテンツが配信される可能性がある
- **バージョン付きURL**(例: `style.v2.css`): キャッシュヒット率を維持しつつ即時更新が可能だが、URL管理が複雑になる
- **即時無効化API**: 素早い反映が可能だがCDNコストが発生し、数十秒の伝播遅延がある
- **サロゲートキー**: 関連するコンテンツグループを一括無効化できる(Cloudflare Cache Tagsなど)
実際の運用では、静的アセット(JS/CSS)はバージョン付きURL、APIレスポンスは短いTTLと即時無効化の組み合わせを使用します。
현재 단락 (1/319)
1. [ネットワーク基礎: OSI & TCP/IP](#1-ネットワーク基礎)