目录
- 网络基础: OSI & TCP/IP
- 套接字编程: asyncio & aiohttp
- 服务网格: Istio & Envoy
- 网络安全: TLS & Zero Trust
- CDN & 边缘计算
- AI 服务网络: gRPC & SSE
- 抓包分析实战
- 测验
1. 网络基础
OSI 7 层模型
OSI(Open Systems Interconnection)模型是把网络通信抽象为 7 个层次的参考模型。
| 层 | 名称 | 协议示例 | PDU |
|---|---|---|---|
| 7 | Application | HTTP, DNS, SMTP | Message |
| 6 | Presentation | TLS, JPEG, ASCII | Message |
| 5 | Session | NetBIOS, RPC | Message |
| 4 | Transport | TCP, UDP | Segment |
| 3 | Network | IP, ICMP | Packet |
| 2 | Data Link | Ethernet, 802.11 | Frame |
| 1 | Physical | 线缆、光纤 | Bits |
TCP/IP 协议栈
实际的互联网使用比 OSI 更简化的 4 层 TCP/IP 模型。
- Application Layer:HTTP/2、HTTP/3、DNS、TLS
- Transport Layer:TCP(可靠性)、UDP(速度)
- Internet Layer:IPv4、IPv6、ICMP
- Link Layer:Ethernet、Wi-Fi
HTTP/2 与 HTTP/3 的区别
HTTP/1.1 在一个连接上一次只能处理一个请求,因此会出现队头阻塞(Head-of-Line, HOL blocking)。
HTTP/2 的改进点:
- 多路复用:在一个 TCP 连接上同时处理多个流
- 头部压缩:用 HPACK 算法消除重复的头部
- 服务器推送:无需客户端请求即可主动推送资源
- 二进制分帧:使用二进制帧而非文本
HTTP/3 & QUIC: HTTP/3 运行在 QUIC(基于 UDP)之上而非 TCP,因此连 TCP 层面的队头阻塞也一并解决了。
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 时的流程:
- 检查浏览器缓存
- 检查 OS 缓存(
/etc/hosts) - 向 Recursive Resolver(ISP DNS)发起查询
- 按 Root NS →
.comTLD NS →example.comAuthoritative NS 的顺序层层查询 - 返回 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 服务器
import asyncio
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 客户端
import asyncio
import aiohttp
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 与 REST 对比
| 项目 | gRPC | REST |
|---|---|---|
| 协议 | HTTP/2 | HTTP/1.1 or HTTP/2 |
| 序列化 | Protocol Buffers(二进制) | JSON(文本) |
| 流式传输 | 支持双向流式传输 | 有限(SSE、WebSocket 需另行搭建) |
| 类型安全 | 强类型(.proto 模式) | 弱类型 |
| 延迟 | 低 | 相对更高 |
| 浏览器支持 | 需要 grpc-web | 原生支持 |
3. 服务网格
Istio 架构
Istio 以边车(sidecar)模式把 Envoy 代理注入每个 Pod,从而控制服务间通信。
- Control Plane(Istiod):管理配置、签发证书、下发流量策略
- Data Plane(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
负载均衡算法
- Round Robin:按顺序分散(默认值)
- Least Connections:选择活跃连接数最少的服务器
- Weighted Round Robin:基于权重分散
- IP Hash:以客户端 IP 固定到特定服务器(会话保持)
- Consistent Hashing:在分布式缓存环境下增减服务器时,将重新分布降到最低
服务发现
在 Kubernetes 环境中,由 CoreDNS 负责服务发现。以 service-name.namespace.svc.cluster.local 的格式访问服务。
4. 网络安全
TLS 证书链
Root CA (最上层证书机构,内置于浏览器/操作系统)
└── Intermediate CA (中间证书机构)
└── Leaf Certificate (实际的服务器证书)
每张证书都由上一级 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 Stapling
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)"
- 基于身份的访问控制:以用户/服务身份而非 IP 地址进行认证
- 最小权限原则:只允许访问必要的资源
- 持续验证:会话期间也持续评估信任等级
- 微分段(Micro-segmentation):把网络划分为更小的区域,阻断横向移动
JWT & OAuth 2.0
JWT(JSON Web Token)由三部分组成:
Header.Payload.Signature
OAuth 2.0 授权码流程(Authorization Code Flow):
- 客户端重定向到 Authorization Server
- 用户完成认证后,签发 Authorization Code
- 后端用 Code 换取 Access Token
- 用 Access Token 调用 Resource Server API
5. CDN & 边缘计算
CDN 工作原理
CDN(Content Delivery Network)通过在全球各地的 PoP(Point 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 服务器:
import grpc
from concurrent import futures
import inference_pb2
import inference_pb2_grpc
import numpy as np
import time
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 生成 token 等场景)
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
import asyncio
import json
app = FastAPI()
async def llm_token_generator(prompt: str):
"""以 SSE 格式流式发送 LLM token"""
# 实际环境中应使用 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) # 模拟 token 生成延迟
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(Round-Trip Time):数据包往返时间,用
ping测量 - Throughput:单位时间的传输数据量,用
iperf3测量 - Packet Loss:丢包率,在不稳定的 UDP 环境中尤为重要
- Jitter:RTT 的抖动,对实时流式传输很重要
# 测量网络带宽
iperf3 -s # 服务器
iperf3 -c server_ip -t 30 -P 4 # 客户端(4 个并行流)
测验
Q1. 请说明 TCP 三次握手与四次挥手的过程。
答案:
三次握手(建立连接):
- Client → Server: SYN (seq=x)
- Server → Client: SYN-ACK (seq=y, ack=x+1)
- Client → Server: ACK (ack=y+1)
四次挥手(断开连接):
- Client → Server: FIN
- Server → Client: ACK
- Server → Client: FIN
- Client → Server: ACK (经过 TIME_WAIT 状态后彻底断开)
解析:断开连接需要四步,是因为服务器收到 FIN 之后可能仍有数据要发送。客户端发出 ACK 之后会维持 TIME_WAIT 状态 2MSL(Maximum Segment Lifetime)的时长,以处理延迟到达的数据包。
Q2. 请说明 HTTP/2 的多路复用如何解决 HTTP/1.1 的队头阻塞问题。
答案:HTTP/2 在一个 TCP 连接上同时传输多个流。每个流都有独立的 ID,某一个流的处理被延迟,也不会影响到其他流。
解析:HTTP/1.1 虽然支持流水线(pipelining),但响应必须按请求顺序返回,前面的响应一慢,后面的响应也要跟着等待(队头阻塞)。HTTP/2 通过按帧交错传输解决了这一问题,但 TCP 层面的队头阻塞,要到 HTTP/3(QUIC)才彻底解决。
Q3. 请说明 mTLS 与普通 TLS 的区别,以及它在服务网格中的作用。
答案:普通 TLS 只验证服务器证书,而 mTLS(Mutual TLS)要求客户端也出示证书,实现双向认证。
解析:在服务网格(如 Istio)中,mTLS 由边车代理(Envoy)自动处理。每个服务都会被签发一张带有唯一 SPIFFE ID 的 X.509 证书,服务间通信时据此完成相互认证与加密。这样即使在内部网络中,也能防止窃听、伪造和中间人攻击。
Q4. 请说明为什么 gRPC 比 REST API 更适合 ML 模型服务。
答案:gRPC 使用 Protocol Buffers 做二进制序列化,基于 HTTP/2 多路复用,并支持双向流式传输,因此在 ML 服务场景中更为优化。
解析:在传输大体量张量数据时,Protocol Buffers 生成的负载体积比 JSON 小 3-5 倍。通过服务器端流式传输,可以把 LLM 生成的 token 实时传给客户端。此外,.proto 模式清晰定义了 API 契约,在 ML 流水线集成时能保证类型安全。
Q5. 请说明 CDN 缓存失效(invalidation)策略的种类及其权衡。
答案:主要策略包括基于 TTL 的过期、基于版本的 URL、通过 API 的即时失效,以及基于代理键(标签)的失效。
解析:
- 基于 TTL:实现简单,但在过期之前可能会提供陈旧内容
- 版本化 URL(
style.v2.css):既保持缓存命中率,又能立即更新,缺点是 URL 管理更复杂 - 即时失效 API:能快速生效,但会产生 CDN 费用,且存在传播延迟(数十秒)
- 代理键(Surrogate Key):可以一次性使一组相关内容失效(如 Cloudflare Cache Tags)
在实际运维中,通常组合使用:静态资源(JS/CSS)用版本化 URL,API 响应用短 TTL + 即时失效。
현재 단락 (1/320)
1. [网络基础: OSI & TCP/IP](#1-网络基础)