模型路由里 Python 的内存坑,以及为什么有人选 C#
AI 模型路由本质上是一个 HTTP 网关——收到请求,解析意图,挑一个后端模型,把结果返回。这层逻辑不复杂,复杂的是它自己要扛住高并发,不能比后面的模型先挂。
路由的核心任务
路由要做的无非这几件事:
- 请求解析与分发:根据 prompt 或参数判断该走哪个模型,比如文本情感分析调 BERT,图像生成调 Stable Diffusion。
- 负载均衡与排队:多个模型实例,得在它们间分摊压力。有时还得支持优先级,防止长任务饿死短任务。
- 熔断与降级:某个模型超时或错误率飙升,自动踢掉,切到备用模型或兜底回复。
这些任务用任何语言都能写,但到了高并发就不一样了。
flowchart LR
A[用户请求] --> B{路由决策中心}
B -- "需要情感分析" --> C[Python BERT 模型]
B -- "需要图像生成" --> D[C# Stable Diffusion]
B -- "简单问答" --> E[轻量 ONNX 模型]
C & D & E --> F[结果聚合返回]
Python:快上手,慢在线上
Python 在 AI 圈是事实标准,模型库、示例代码几乎都是 Python 的。用 FastAPI 或 Flask 搭个路由一天就能跑起来。但一上量,问题就来了。
最常见的是内存。Python 的垃圾回收对循环引用、大对象不那么利索,请求一来一去,内存就悄悄涨上去。加上模型推理往往是 CPU/GPU 密集的,线程池开多了,GIL 倒不是最要命的,要命的是每个线程都占内存,开着开着就报 RuntimeError: Cannot allocate memory。我也遇到过 Thread pool exhausted,因为默认线程池太小,而请求一直在排队。
缓解的办法不是没有:用进程模型(gunicorn + uvicorn workers)、限制最大并发数、引入消息队列把推理异步化。但这堆操作下来,路由层本身就不轻了。
C# 的诱惑与尴尬
C# 系(ASP.NET Core)在高并发 Web 服务上口碑不错。async/await 是语言级的,线程池管理成熟,内存由 CLR 托管,很少出现野指针式的泄漏。写路由服务,每秒几千请求可以压得很平。但它的短板是 AI 生态:ONNX Runtime 的 C# 绑定能用,但周边工具少,调模型的时候经常得从 Python 那边'偷'些预处理代码。如果你要跑 Transformers,基本还是得靠 Python 服务,C# 路由只是把请求转发过去。
所以现实中的折中是:路由代理用 C# 写,模型推理用 Python 服务,中间走 gRPC 或 HTTP。这样既拿了 C# 的稳,又不丢 Python 的模型库。不过多一层转发,延迟会加一点,看你取舍。
选型没有标准答案
说实话,小规模随便用,Python 一把梭没问题。等日请求破百万,或者对延迟敏感,就得计较语言开销了。有人全部转到 C#,用 ML.NET 做轻量推理,然后重度模型调 Python 微服务——这种分层现在越来越多。
选型的核心不是语言本身,而是你团队维护哪种代码更顺手,以及线上排障脑子里有没有那根弦:路由崩了,模型再快也白搭。


