net/http 直接起服务够用但需手动处理路由、错误等,常见404/500/timeout问题;建议用timeouthandler、context超时、避免log.fatal、正确设置sse头;gin可简化json编解码、中间件、错误统一;流式响应须flush;模型超时应分层控制。

用 net/http 直接起服务,够用但得自己管路由和错误
直接用 net/http 启一个 HTTP 服务调用 AI 模型,是最快验证逻辑的方式,适合本地调试或轻量部署。但它不处理路径分组、中间件、JSON 自动编解码这些事,所有事情都得手动写。
常见错误现象包括:404 Not Found(没注册 handler)、500 Internal Server Error(panic 没 recover)、EOF 或 io: read/write timeout(模型响应慢导致连接被关)。
实操建议:
- 务必用
http.TimeoutHandler包裹 handler,避免模型卡住整个 server - 对每个请求启动 goroutine 调用模型时,加
context.WithTimeout控制最大等待时间 - 不要在 handler 里直接
log.Fatal,会 kill 整个 server;改用log.Printf+ 返回http.Error - 如果模型返回流式数据(如 SSE),必须设置
ResponseWriter.Header().Set("Content-Type", "text/event-stream")和禁用缓存
Gin 框架集成 Ollama / TensorFlow Serving,省掉重复胶水代码
用 Gin 替代原生 net/http,主要价值在统一处理 JSON 输入/输出、参数绑定、中间件链、日志格式和错误响应结构。尤其对接 Ollama(http://localhost:11434/api/generate)或 TensorFlow Serving(http://tf-serving:8501/v1/models/model:predict)这类后端时,能快速组织请求体、解析响应、透传错误码。
关键差异点:
-
Gin.Context.BindJSON()自动校验字段类型和 required tag,比手写json.Unmarshal少一堆 if err != nil - 用
c.AbortWithStatusJSON(400, gin.H{"error": "invalid prompt"})统一错误格式,前端不用猜字段名 - 模型调用失败时,别直接 return 错误,要用
c.Error(err)让 Gin 的 Recovery 中间件捕获 panic - 若需并发压测,记得给
http.Client设置Transport.MaxIdleConnsPerHost,否则默认 2 会成瓶颈
流式响应(SSE)必须手动 flush,不然前端收不到 chunk
调用支持流式输出的模型(比如 Ollama 的 /api/chat 或自建 LLM 推理服务)时,用 text/event-stream 是最常用方案。但 Go 的 http.ResponseWriter 默认带缓冲,不显式 Flush() 就不会发数据到客户端。
容易踩的坑:
- 忘记调用
c.Writer.(http.Flusher).Flush(),导致前端一直 loading - 在循环中写了
c.SSEvent("data", ...)却没检查err := c.Writer.Flush(),网络断开后继续写会 panic - 没设
Header().Set("Cache-Control", "no-cache"),某些代理或浏览器会缓存首条 event - 用
time.Sleep模拟流式延迟没问题,但生产环境应由模型 SDK 自带流式 callback 驱动,而非轮询
模型调用超时与重试要分层控制,不能全扔给 client.Timeout
AI 模型推理耗时波动大:冷启加载权重可能几百毫秒,GPU 显存不足时排队几秒,Ollama 在 CPU 模式下跑 llama3:8b 可能稳定在 800ms/token。只靠 http.Client.Timeout 会误杀合理长请求。
推荐分层控制:
- HTTP 层:设
Timeout = 30s,防 socket hang - Context 层:handler 入口用
ctx, cancel := context.WithTimeout(c.Request.Context(), 20*s),留 10s 给网络抖动 - 模型层:Ollama 的
stream请求本身支持options.timeout字段(单位秒),优先走这个 - 重试:仅对 5xx 或连接失败重试,绝不对 400(如 prompt 过长)重试;最多 1 次,且用指数退避
真正难处理的是模型进程僵死、GPU OOM 后无响应这类情况——这时得靠外部健康检查(如定期 GET /health)+ 进程级 watchdog,HTTP 层做不了。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











