第五章:实战串联——调用 AI API 时发生了什么?
前面我们分别学了 TCP 和 HTTP,本章把它们串起来。
通过一个完整的例子,看看你写的一行
requests.post(...)背后,到底经历了哪些步骤。
5.1 一行代码背后的完整旅程
当你执行下面这段代码时:
import requests
response = requests.post(
"https://api.openai.com/v1/chat/completions",
headers={
"Authorization": "Bearer sk-你的密钥",
"Content-Type": "application/json"
},
json={
"model": "gpt-4",
"messages": [{"role": "user", "content": "你好"}]
}
)
底层依次发生了 7 个步骤:
步骤 1 DNS 解析
────────────────────────────────
你的电脑:"api.openai.com 的 IP 地址是多少?"
DNS 服务器:"是 104.18.7.192"
│
▼
步骤 2 TCP 三次握手
────────────────────────────────
你的电脑 → SYN → OpenAI 服务器
你的电脑 ← SYN+ACK ← OpenAI 服务器
你的电脑 → ACK → OpenAI 服务器
(TCP 连接建立成功)
│
▼
步骤 3 TLS 握手(因为是 HTTPS)
────────────────────────────────
双方协商加密方式,交换密钥
(此后所有数据都加密传输)
│
▼
步骤 4 发送 HTTP 请求
────────────────────────────────
你的电脑通过 TCP 连接,发送:
POST /v1/chat/completions HTTP/1.1
Host: api.openai.com
Authorization: Bearer sk-你的密钥
Content-Type: application/json
{"model":"gpt-4","messages":[{"role":"user","content":"你好"}]}
│
▼
步骤 5 服务器处理请求
────────────────────────────────
OpenAI 服务器收到请求
→ 验证 API Key
→ 解析参数
→ 调用 GPT-4 模型生成回答
→ 构造 HTTP 响应
│
▼
步骤 6 接收 HTTP 响应
────────────────────────────────
OpenAI 服务器通过同一个 TCP 连接返回:
HTTP/1.1 200 OK
Content-Type: application/json
{"choices":[{"message":{"content":"你好!有什么可以帮助你的?"}}]}
│
▼
步骤 7 断开连接
────────────────────────────────
TCP 四次挥手,连接关闭
(或保持连接供后续请求复用)
时间分布(大致)
DNS 解析 ██ ~10ms
TCP 三次握手 ████ ~30ms
TLS 握手 ██████ ~50ms
发送请求 █ ~5ms
服务器处理 ██████████████████████████ ~500ms-数秒(AI 生成耗时)
接收响应 ██ ~10ms
断开连接 ██ ~10ms
可以看到,大部分时间花在服务器处理(AI 生成回答)上。连接建立的开销虽然不大,但如果频繁建立新连接,累加起来也不可忽视。
5.2 用 Python 逐步体验
体验一:最简单的 GET 请求
import requests
# 发一个 GET 请求,获取你的公网 IP 信息
response = requests.get("https://httpbin.org/ip")
print(f"状态码:{response.status_code}")
print(f"响应头:{dict(response.headers)}")
print(f"响应体:{response.text}")
运行结果类似:
状态码:200
响应头:{'Content-Type': 'application/json', ...}
响应体:{"origin": "116.23.45.67"}
体验二:带参数的 GET 请求
# URL 参数会自动拼接到 URL 后面
response = requests.get(
"https://httpbin.org/get",
params={"name": "张三", "age": "20"}
)
# 实际发送的 URL: https://httpbin.org/get?name=张三&age=20
print(response.json())
体验三:POST 请求发送 JSON
# 发送 JSON 数据
response = requests.post(
"https://httpbin.org/post",
json={"message": "你好,世界"}
)
result = response.json()
print(f"服务器收到的数据:{result['json']}")
体验四:查看完整的请求信息
response = requests.post(
"https://httpbin.org/post",
headers={"X-My-Header": "hello"},
json={"key": "value"}
)
# httpbin.org 会把你发送的所有信息原样返回
result = response.json()
print(f"请求头:{result['headers']}")
print(f"请求体:{result['json']}")
print(f"请求方法:POST")
print(f"URL:{result['url']}")
体验五:模拟调用 AI API(不需要 API Key)
# 使用 httpbin 模拟一个 API 调用流程
api_url = "https://httpbin.org/post"
request_body = {
"model": "gpt-4",
"messages": [
{"role": "system", "content": "你是一个助手"},
{"role": "user", "content": "什么是 HTTP?"}
]
}
response = requests.post(
api_url,
headers={
"Authorization": "Bearer sk-fake-key-12345",
"Content-Type": "application/json"
},
json=request_body
)
print(f"状态码:{response.status_code}")
print(f"服务器收到的 Authorization 头:{response.json()['headers'].get('Authorization')}")
print(f"服务器收到的请求体:{response.json()['json']}")
5.3 用浏览器开发者工具观察
这是最直观的学习方式,强烈推荐动手操作。
步骤
- 打开 Chrome 浏览器
- 按 F12 打开开发者工具
- 切换到 Network(网络) 标签
- 在地址栏访问任意网站(如
https://www.baidu.com) - 你会看到大量的网络请求
观察要点
点击任意一条请求,查看:
General(概览)
├── Request URL:请求的完整 URL
├── Request Method:GET / POST / ...
└── Status Code:200 / 404 / ...
Request Headers(请求头)
├── Host:目标服务器
├── User-Agent:你的浏览器信息
├── Accept:期望的响应格式
└── Cookie:登录状态信息
Response Headers(响应头)
├── Content-Type:响应数据格式
├── Content-Length:数据大小
└── Set-Cookie:服务器设置的 Cookie
Response(响应体)
└── 服务器返回的实际数据(HTML / JSON / 图片等)
重点看什么
| 观察项 | 对应知识点 |
|---|---|
| Method 列显示 GET/POST | HTTP 请求方法 |
| Status 列显示 200/304/404 | HTTP 状态码 |
| Type 列显示 document/xhr/json | 资源类型 |
| Time 列显示耗时 | 包含 TCP 连接 + 请求处理时间 |
| Waterfall 瀑布图 | 可视化请求的各阶段耗时 |
5.4 用 curl 观察完整过程
curl 是一个命令行 HTTP 工具,加上 -v 参数可以看到完整的通信过程:
curl -v https://httpbin.org/get
输出示例(简化版):
* Trying 3.230.204.70:443... ← DNS 解析后的 IP
* Connected to httpbin.org ← TCP 连接建立
* SSL connection established ← TLS 握手完成
> GET /get HTTP/1.1 ← 你发送的 HTTP 请求
> Host: httpbin.org ← 请求头
> User-Agent: curl/8.1.2 ← 请求头
> Accept: */* ← 请求头
< HTTP/1.1 200 OK ← 服务器的 HTTP 响应
< Content-Type: application/json ← 响应头
< Content-Length: 256 ← 响应头
{ ← 响应体
"headers": { ... },
"origin": "116.23.45.67",
"url": "https://httpbin.org/get"
}
* Connection #0 left intact ← 连接保持(复用)
>开头的行是你发出去的(请求),<开头的行是收到的(响应),*开头的行是 curl 的说明。
5.5 常见问题排查指南
当你的代码报错时,按这个思路逐层排查:
第一步:判断是哪一层的问题
能不能连上? ─── 不能 ──→ TCP 层问题(网络/端口/防火墙)
│
能
│
▼
状态码是多少? ─── 4xx ──→ 你的请求有问题(HTTP 层)
│ │
│ 401 → 检查 API Key
│ 403 → 检查权限
│ 404 → 检查 URL
│ 429 → 降低频率
│
200
│
▼
响应内容对吗? ─── 不对 ──→ 解析逻辑有问题(代码层)
│
对
│
▼
✅ 一切正常
第二步:常见错误对照表
| 错误信息 | 层级 | 原因 | 解决办法 |
|---|---|---|---|
ConnectionTimeout | TCP | 连不上服务器 | 检查网络、域名、端口 |
ConnectionRefused | TCP | 端口没开 | 确认服务器和端口 |
SSLError | TLS | 证书问题 | 更新 CA 证书 |
401 Unauthorized | HTTP | 身份验证失败 | 检查 API Key |
400 Bad Request | HTTP | 请求格式错 | 检查 JSON 和参数 |
429 Too Many Requests | HTTP | 频率太高 | 加延时重试 |
500 Internal Server Error | HTTP | 服务器问题 | 等待并重试 |
JSONDecodeError | 代码 | 响应不是 JSON | 先打印 response.text 看原始内容 |
第三步:调试代码模板
import requests
try:
response = requests.post(
"https://api.openai.com/v1/chat/completions",
headers={
"Authorization": "Bearer sk-你的密钥",
"Content-Type": "application/json"
},
json={
"model": "gpt-4",
"messages": [{"role": "user", "content": "你好"}]
},
timeout=30
)
print(f"状态码:{response.status_code}")
if response.status_code == 200:
result = response.json()
print(f"AI 回答:{result['choices'][0]['message']['content']}")
else:
print(f"请求失败!")
print(f"状态码:{response.status_code}")
print(f"错误信息:{response.text}")
except requests.exceptions.ConnectionError:
print("连接失败!请检查网络和服务器地址。")
except requests.exceptions.Timeout:
print("请求超时!服务器可能无响应。")
except requests.exceptions.RequestException as e:
print(f"请求异常:{e}")
5.6 性能优化小提示
了解了 TCP 和 HTTP 的原理后,你自然就能理解这些优化手段:
| 优化手段 | 原理 | 效果 |
|---|---|---|
使用 requests.Session() | 复用 TCP 连接,避免重复握手 | 减少连接开销 |
设置合理的 timeout | 避免请求无限等待 | 提高程序健壮性 |
| 批量请求代替多次单请求 | 减少 HTTP 请求次数 | 降低总耗时 |
使用异步请求(aiohttp) | 并发发送多个请求 | 大幅提升吞吐量 |
Session 复用示例
import requests
session = requests.Session()
session.headers.update({
"Authorization": "Bearer sk-你的密钥",
"Content-Type": "application/json"
})
# 多次请求复用同一个 TCP 连接
for question in ["你好", "什么是 AI?", "谢谢"]:
response = session.post(
"https://api.openai.com/v1/chat/completions",
json={
"model": "gpt-4",
"messages": [{"role": "user", "content": question}]
}
)
print(response.json()["choices"][0]["message"]["content"])
本章小结
- 一次 API 调用经历:DNS 解析 → TCP 握手 → TLS 握手 → HTTP 请求 → 服务器处理 → HTTP 响应 → 断开连接
- 用 Python
requests库可以轻松发送 HTTP 请求 - 浏览器 F12 和 curl -v 是观察 HTTP 通信的利器
- 遇到问题先判断层级:TCP 层(连不上)→ HTTP 层(状态码异常)→ 代码层(解析错误)
- 用 Session 复用连接可以提升性能
下一章是选学内容,介绍 JSON、流式响应等补充知识。
← 上一章:HTTP 协议 | 下一章:补充知识 →