最直接的pv统计方式是在fiber全局中间件中对html页面路径(如/、/article/123)匹配正则^/($|[^?#]*\.html?$)后计数,需过滤爬虫ua、健康检查header、静态资源及api路径,并在ctx.next()后按200状态码且返回html才计数,推荐redis incr或异步日志聚合。

Fiber 框架本身不提供 PV 统计功能,必须自行实现中间件或钩子捕获请求,且需注意区分真实用户行为与爬虫、健康检查等干扰流量。
如何用 Fiber 中间件统计单次页面访问(PV)
最直接的方式是在全局中间件中对 ctx.Path() 或 ctx.Request().URL.Path 计数,但要注意:不是所有请求都算 PV。比如静态资源(/static/js/app.js)、API 接口(/api/user)、健康检查(/health)通常不应计入。
- 只对 HTML 页面路径(如
/、/article/123、/about)做计数,可通过正则匹配^/($|[^?#]*\.html?$)初筛 - 建议在中间件里加
ctx.Get("user_agent")判断是否为常见爬虫 UA(如HeadlessChrome、bot、crawler),直接跳过计数 - 避免在重定向响应(
ctx.Redirect)或错误响应(ctx.Status(404))后重复计数 - 若使用 Redis,推荐用
INCR命令写入带时间戳的 key,例如pv:20260905:/,便于后续按日/路径聚合
如何识别并过滤无效 PV 请求
大量 PV 数据失真,往往源于未过滤非人为请求。Fiber 的 ctx.Request().Header.Get("User-Agent") 和 ctx.GetReqHeaders() 是关键判断依据。
- 排除已知监控探针:检查
ctx.Request().Header.Get("X-Monitor-Source")或自定义 Header(如X-Health-Check) - 拦截空 UA 或极简 UA(长度
- 对高频 IP(如 1 秒内 > 5 次相同路径请求)做临时限流或标记为“疑似采集”,不计入 PV
- 注意:不要依赖
Referer过滤,它易伪造且移动端常为空
如何保证统计不丢失、不重复
Fiber 默认不保证中间件执行完成才返回响应,尤其在 panic 恢复或提前 ctx.SendString 后,计数逻辑可能被跳过。
- 把计数逻辑放在中间件末尾,并确保它不 panic;若用 Redis,建议设置超时(如
context.WithTimeout)防止阻塞 - 避免在
ctx.Next()前计数——否则 404 或重定向也会被记一次;应放在ctx.Next()后,再根据ctx.Response().StatusCode()判断是否成功返回 HTML - 如果业务允许轻微误差,可用异步写入(
go func() { ... }()),但需注意 Go 的 goroutine 生命周期 —— 不要引用ctx或其内部字段 - 更稳妥的做法是记录原始日志行(
log.Printf("%s %s %s", ip, method, path)),后续用 Logstash 或 Loki 聚合,而非实时计数
真正难的不是“怎么加一行 INCR”,而是确定哪类请求该进 PV、哪类该过滤、以及当服务高并发或崩溃时,统计链路是否还能保持语义一致。线上跑一周后,务必比对 Nginx 日志里的 200 GET /.*\.html? 行数,验证你的中间件有没有漏判或多计。











