revel基准性能测试需剥离开发模式干扰,使用revel build生成二进制、设mode=prod、禁用调试filter、启用控制器复用、预热路由、绕过localhost压测,并调优日志与连接策略。

Revel 项目做基准性能测试,不能直接跑 revel run 然后用 wrk 打本地 localhost:9000 —— 那测的不是框架吞吐,是开发模式下的热重载、模板编译、日志输出和调试中间件的总和。真实基准值要剥离这些干扰项,从构建产物出发,用生产配置压测。
用 revel build 生成可执行文件再压测
开发时用 revel run 启动的服务默认启用所有调试 Filter(PanicFilter、ValidationFilter、InterceptorFilter 等),还会动态编译模板、检查文件变更。这些在基准测试中必须关闭。
- 执行
revel build -a myapp -d /tmp/myapp-build,生成独立二进制 - 修改
conf/app.conf中的mode=prod,并显式禁用调试类 Filter:revel.intercept.enabled=false、revel.validation.enabled=false - 启动前确保
revel.app.log.level=ERROR,避免日志 I/O 拖慢吞吐 - 用
./myapp -conf conf/app.conf -port 8080启动,不带任何开发参数
wrk 压测时必须绕过 Revel 的默认路由缓存机制
Revel 内部用 actionPathCacheMap 缓存路由解析结果,但这个缓存只在第一次请求后生效。如果压测前没预热,前几秒的请求会触发大量锁竞争和 map 初始化,导致 p99 延迟虚高、QPS 波动剧烈。
- 压测前先用
wrk -c 1 -t 1 -d 2s http://localhost:8080/发 1–2 个请求预热 - 确保压测命令开启 keep-alive:
wrk -t4 -c100 -d30s --latency http://localhost:8080/(-c100是连接数,不是并发数) - 避免使用
localhost:压测机和服务端必须分物理机或至少分容器,否则 TCP 回环路径会掩盖真实网络栈开销 - 禁用客户端 DNS 查询:在 hosts 文件里写死服务端 IP,防止
wrk解析耗时污染结果
控制器对象池必须启用,否则 GC 会吃掉 30%+ QPS
Revel 默认每个请求都 new 一个控制器实例,高并发下对象分配 + GC 压力极大。实测显示,未启用复用时,每秒 1000 请求下 GC 次数达 23 次/分钟;启用后降到 5 次/分钟,平均延迟从 45ms 降到 12ms。
- 在
conf/app.conf中设置:revel.controller.reuse=true - 调大池容量以匹配预期并发:
revel.controller.stack=50、revel.controller.maxstack=500 - 注意:复用要求控制器方法不能持有 request-scoped 闭包或未清理的字段,否则会引发数据污染
- 验证是否生效:压测中观察
go tool pprof http://localhost:8080/debug/pprof/heap,对比启用前后对象分配速率
真正卡住 Revel 基准性能的,往往不是路由或 JSON 序列化,而是控制器生命周期管理 + 日志级别 + 连接策略这三者的组合效应。漏掉其中任意一项,测出来的数字就只是“某个特定配置下的瞬时快照”,没法横向比,也没法指导扩容决策。











