Iris 性能优化需复用 gRPC 连接、禁用日志体打印、静态文件交由 sendfile 处理:全局复用 grpc.Dial 并正确注入;gRPC 调用必须用 context.WithTimeout 包裹并 defer cancel;LogRequestBody/Response 设为 false;静态资源用 iris.Dir 启用 sendfile。

直接复用 gRPC 连接、关掉日志体打印、静态文件交给 sendfile——这三件事不做,Iris 的“快”就只剩宣传稿里的字面意思。
为什么每次请求都 grpc.Dial 会炸掉服务
常见错误现象:too many open files 报错频发,QPS 上不去,CPU 持续偏高但实际吞吐没涨。
根本原因不是并发太高,而是每个 HTTP 请求都在新建 gRPC 连接:DNS 解析、TLS 握手、TCP 建连全重来一遍,还顺带耗尽 fd。
- 正确做法:在
app.Run()前全局调用一次grpc.Dial,传入grpc.WithBlock()确保初始化成功 - 注入方式必须用
app.RegisterValue(&itempb.ItemServiceClient{}, client),别往 controller struct 字段里声明接口类型——Iris 不支持字段级接口注入 - 后续在控制器方法参数中直接接收
itempb.ItemServiceClient即可,框架自动注入
context.WithTimeout 必须套在 gRPC 调用上,不是 HTTP 层
HTTP 超时(比如 ctx.SetReadTimeout)对 gRPC 底层连接完全无效。后端卡住时,goroutine 就挂在那里等满超时时间,线程池慢慢被吃光。
- 从
ctx.Request().Context()派生新 context:ctx2, cancel := context.WithTimeout(ctx.Request().Context(), 3*time.Second) - 立刻
defer cancel(),否则 context 泄漏风险极高 - 如需透传 trace 或 request ID,用
metadata.AppendToOutgoingContext注入到这个新 ctx,再传给client.GetItem(ctx2, req)
禁用 LogRequestBody 和 LogResponseBody
默认开启时,中间件会强制调用 ctx.ReadBody() 缓存整个请求体,尤其是大 JSON 或表单上传,内存分配飙升,GC 频繁拖慢响应。
- 生产环境务必设为
LogRequestBody: false和LogResponseBody: false - 调试时改用条件日志:只对
statusCode >= 400或特定路径(如/debug/)记录简要信息 - 绝对不要在中间件里调用
ctx.PostValues()或ctx.ReadForm()——body 被提前消费,后续 handler 就读不到数据了
静态文件别走 iris.FileServer,让 OS 处理
iris.FileServer 是纯 Go 实现,对 >1MB 文件或高并发静态资源请求,CPU 和内存开销远高于系统级 sendfile 系统调用。
- 直接用
app.HandleDir("/assets", iris.Dir("./assets"))是安全的,它底层已适配 sendfile - 避免自己写 handler 去读文件再
ctx.ServeContent,那等于绕过优化路径 - 如果用了反向代理(如 Nginx),更应把静态资源完全剥离出 Iris 进程,由代理直接 serve
最容易被忽略的是 context 生命周期管理——WithTimeout 后不 defer cancel(),跑几天后 goroutine 数会悄悄翻倍;还有人以为 LogRequestBody: false 只是少打点日志,其实它直接省掉了 body 的内存拷贝和 GC 压力。这些点不抠细,性能优化就只是调参游戏。



















