【软件工程】Web架构基础知识
核心组件
Web服务器(HTTP Server)
- 作用:接收HTTP请求,返回响应
- 代表:nginx、Apache、Caddy、Lighttpd
- 特点:擅长静态文件服务、反向代理、负载均衡,不处理业务逻辑
Web框架(Application Framework)
- 作用:写核心业务逻辑的工具
- Python系:Flask(轻量级)、Django(重量级)、FastAPI(异步)
- 其他语言:Express.js (Node.js)、Spring Boot (Java)、Rails (Ruby)、Laravel (PHP)、Gin (Go)
- 特点:处理业务逻辑(数据库、API、认证),自带简易HTTP服务器(仅开发用)
WSGI/ASGI服务器(应用服务器)
- 作用:连接Web服务器和Python应用的桥梁
- 代表:Gunicorn(多进程)、uWSGI(功能强大)、Uvicorn(异步)、Waitress(跨平台)
- 为什么需要:Flask自带服务器只适合开发,生产环境需要多进程/多线程,更好的性能和稳定性
类比
- Web服务器(nginx)= 专业服务员(只负责端菜,速度快100倍)
- Web框架(Flask)= 厨师(会做菜,也能端菜,但端菜慢)
- 应用服务器(Gunicorn)= 传菜员(协调厨师和服务员)
关键概念对比
1. 静态文件 vs 动态内容
| 对比维度 | 静态文件 | 动态内容 |
|---|---|---|
| 内容类型 | HTML、CSS、JS、图片 | API响应、个性化内容 |
| 是否需要计算 | 否,内容固定 | 是,需要查数据库/计算 |
| 适合的服务器 | nginx直接服务 | 应用框架处理 |
| 性能 | 极快(直接读取文件) | 较慢(需要业务逻辑) |
| 示例 | /css/style.css |
/api/patient/123 |
2. 反向代理 vs 正向代理
| 对比维度 | 反向代理 | 正向代理 |
|---|---|---|
| 流程 | 用户 → nginx → 后端服务器 | 用户 → 代理 → 目标网站 |
| 谁不知道真实地址 | 用户不知道真实服务器 | 目标网站不知道真实用户 |
| 代表谁 | 代表服务器接收请求 | 代表用户发送请求 |
| 使用场景 | 负载均衡、隐藏后端 | VPN、翻墙 |
3. 同步 vs 异步
| 对比维度 | 同步(Flask默认) | 异步(FastAPI) |
|---|---|---|
| 处理方式 | 一次处理一个请求 | 同时处理多个请求 |
| 等待IO时 | 阻塞,什么都不做 | 不阻塞,处理其他请求 |
| 代码复杂度 | 简单 | 复杂(需要async/await) |
| 性能 | 较低 | 高 |
| 适用场景 | 简单应用、CPU密集 | 高并发、IO密集 |
典型架构演进
阶段1:开发阶段
graph LR
A[浏览器] --> B[Flask内置服务器<br/>端口50001]
B --> C[业务逻辑 + 静态文件]
问题:
- 单进程,并发能力差
- 静态文件服务慢
- 不适合生产环境
阶段2:小型生产环境
graph LR
A[浏览器] --> B[nginx<br/>端口80/443]
B --> C[静态文件<br/>直接服务]
B --> D[Flask<br/>端口5000]
D --> E[业务逻辑]
改进:
- nginx处理静态文件(快100倍)
- Flask只处理API
- 职责分离
阶段3:中型生产环境(推荐)
graph LR
A[浏览器] --> B[nginx<br/>端口80/443]
B --> C[静态文件]
B --> D[Gunicorn<br/>4个worker]
D --> E[Flask应用]
改进:
- Gunicorn多进程
- 并发能力提升
- 自动重启失败进程
阶段4:大型生产环境
graph TB
A[浏览器] --> B[Cloudflare CDN]
B --> C[nginx<br/>负载均衡]
C --> D[静态文件<br/>CDN缓存]
C --> E[Gunicorn实例]
E --> F[服务器1<br/>4 workers]
E --> G[服务器2<br/>4 workers]
E --> H[服务器3<br/>4 workers]
F --> I[数据库集群]
G --> I
H --> I
改进:
- 水平扩展
- 高可用
- CDN加速
项目实战:内网AI智能体的公网部署
项目背景
我开发了一个基于LangGraph的AI智能体系统,核心组件包括:
- Web前端(HTML/JS)
- Flask API服务器
- LangGraph Agent(工具增强型智能体)
- 内网部署的LLM服务(Qwen、Kimi等)
- MySQL数据库
所有服务都部署在内网,需要通过Cloudflare隧道让公网用户访问。
当前架构
graph TB
subgraph 公网
A[用户浏览器] <--> B[Cloudflare隧道]
end
subgraph 内网_192.168.x.x
B -->|穿透端口50001| C[proxy_server.py<br/>Flask反向代理]
C -->|静态文件| D[HTML/CSS/JS]
C -->|API代理| E[Flask API<br/>端口51002]
E --> F[LangGraph Agent]
F -->|工具调用| G[数据库查询]
F -->|LLM调用| H[内网LLM服务<br/>172.21.8.x:6080]
end
架构特点:
- proxy_server.py 既处理静态文件,又做反向代理
- Flask单进程运行,处理所有请求
- 典型的开发阶段架构
核心问题:公网如何访问内网LLM?
Cloudflare隧道只穿透了50001端口,为什么公网用户能调用内网的LLM服务(172.21.8.x:6080)?
关键点:LLM调用发生在服务器端,不是浏览器端
graph TB
subgraph 错误理解
X1[公网浏览器] -.->|❌ 无法访问| X2[内网LLM<br/>172.21.8.x:6080]
end
subgraph 实际流程
Y1[公网浏览器] -->|✅ HTTPS| Y2[Cloudflare隧道]
Y2 -->|✅ 穿透| Y3[Flask API<br/>内网]
Y3 -->|✅ 内网HTTP| Y4[LLM服务<br/>内网]
end
流程说明:
- 用户浏览器通过HTTPS访问Cloudflare隧道
- 隧道穿透到内网的Flask API服务器
- Flask服务器在内网直接调用LLM服务(内网之间可以直接通信)
- LLM响应通过SSE流式返回给用户
这是典型的BFF(Backend For Frontend)架构:前端只和Web服务器通信,Web服务器在内网调用各种后端服务(LLM、数据库等),后端服务不暴露到公网。
安全优势:
- LLM服务器不暴露到公网
- API密钥存储在服务器端,浏览器看不到
- 只有一个端口穿透,攻击面小
性能瓶颈
| 组件 | 当前方案 | 问题 | 性能 |
|---|---|---|---|
| 静态文件 | Flask处理 | Python层读取文件 | QPS ~150 |
| API服务 | Flask单进程 | 并发能力差 | 并发 ~100 |
| 反向代理 | Flask requests库 | Python层转发 | 延迟高 |
改进方案
方案1:nginx + Flask(推荐)
graph TB
subgraph 公网
A[用户浏览器] <--> B[Cloudflare隧道]
end
subgraph 内网
B -->|穿透| C[nginx<br/>端口50001]
C -->|静态文件| D[直接服务<br/>零拷贝]
C -->|/api/*| E[Flask API<br/>端口51002]
E --> F[LangGraph Agent]
F --> G[LLM服务]
end
改进效果:
- 静态文件性能提升50倍
- 自动gzip压缩,节省带宽60%
- nginx处理静态文件,Flask专注业务逻辑
nginx配置要点:
1 | server { |
方案2:nginx + Gunicorn + Flask(生产级)
graph TB
A[Cloudflare隧道] --> B[nginx]
B --> C[静态文件]
B --> D[Gunicorn<br/>4 workers]
D --> E1[Flask进程1]
D --> E2[Flask进程2]
D --> E3[Flask进程3]
D --> E4[Flask进程4]
E1 --> F[LangGraph Agent]
E2 --> F
E3 --> F
E4 --> F
F --> G[LLM服务]
改进效果:
- 并发能力提升4倍(4个worker进程)
- 自动重启失败进程,稳定性更好
- 生产环境标准方案
评论

