Loading... # NginxPulse 技术分析文档 ## 1. 项目概述 NginxPulse 是一个轻量级的 Nginx 访问日志分析与可视化面板。该项目通过实时解析 Nginx 访问日志,提供 PV 过滤、IP 归属地查询、客户端解析等核心功能,旨在为中小型网站提供低成本的日志监控与分析解决方案。 ### 1.1 核心特性 - **实时统计分析**:定时扫描日志文件,实时更新访问统计 - **智能 PV 过滤**:支持基于状态码、URL 模式、IP 列表的访问过滤 - **IP 归属地解析**:结合远程 API 和本地数据库的多层次 IP 定位策略 - **客户端分析**:解析 User-Agent,识别浏览器、操作系统、设备类型 - **轻量级部署**:单镜像容器化部署,基于 SQLite 存储,无需额外数据库依赖 ### 1.2 技术栈 | 层次 | 技术选型 | |------|----------| | 后端 | Go 1.23.x · Gin · Logrus | | 数据库 | SQLite (modernc.org/sqlite) | | IP 解析 | ip2region(本地)+ ip-api.com(远程) | | 前端 | Vue 3 · Vite · TypeScript · PrimeVue · ECharts/Chart.js · SCSS | | 容器化 | Docker / Docker Compose · Nginx(前端静态部署) | --- ## 2. 系统架构设计 ### 2.1 整体架构图 ```mermaid graph TB subgraph 数据源 NGINX[Nginx 日志文件] end subgraph NginxPulse容器 subgraph 前端层 VUE[Vue 3 应用] NGINX_FRONT[Nginx 静态服务] end subgraph 后端层 INGEST[日志摄入模块] ENRICH[数据增强模块] ANALYTICS[统计分析模块] STORE[数据存储层] API[HTTP API] end subgraph 数据层 SQLITE[(SQLite 数据库)] CACHE[内存缓存] IPDB[ip2region 本地库] end end subgraph 外部服务 IPAPI[ip-api.com] end NGINX --> INGEST INGEST --> ENRICH ENRICH --> ANALYTICS ANALYTICS --> STORE STORE --> SQLITE API --> STORE ENRICH --> CACHE ENRICH --> IPAPI ENRICH --> IPDB VUE --> API VUE --> NGINX_FRONT USER[用户] --> NGINX_FRONT USER --> API ``` ### 2.2 核心模块分析 #### 2.2.1 日志摄入模块 (ingest) 日志摄入模块负责持续监控和解析 Nginx 访问日志: - **扫描机制**:基于游标(cursor)的增量扫描,避免重复解析 - **解析器**:使用正则表达式匹配典型 Nginx access log 格式 - **状态持久化**:扫描位置保存至 `nginx_scan_state.json` #### 2.2.2 数据增强模块 (enrich) 该模块为核心差异点,实现了智能的 IP 归属地查询策略: ``` 快速过滤 → 缓存查询 → 远程批量查询 → 本地兜底查询 ``` **查询策略详解**: 1. **快速过滤**:空值、本地、回环地址返回"本地",内网地址返回"内网/本地网络" 2. **缓存优先**:内存缓存最多存储 50,000 条 IP 查询结果 3. **远程优先**:调用 ip-api.com 批量接口(单批最多 100 个),超时 1.2s 4. **本地兜底**:使用内嵌的 ip2region.xdb 数据库,50ms 超时 5. **IPv6 处理**:仅走远程查询,失败返回"未知" #### 2.2.3 统计分析模块 (analytics) 负责按时间维度聚合访问数据,生成多维统计指标: - PV/UV 统计(按小时/天) - 状态码分布 - 访问路径排行 - 客户端类型分布 - IP 地域分布 #### 2.2.4 数据存储层 (store) 基于 SQLite 的轻量级存储方案: - 表结构设计:访问记录表、统计聚合表 - 写入优化:批量插入,事务管理 - 数据持久化:`nginxpulse.db` --- ## 3. IP 归属地查询策略深度分析 ### 3.1 策略流程图 ```mermaid flowchart TD A[接收 IP 地址] --> B{快速过滤} B -->|空值/本地/回环| C[返回: 本地] B -->|内网地址| D[返回: 内网/本地网络] B -->|正常公网 IP| E{内存缓存检查} E -->|命中| F[返回缓存结果] E -->|未命中| G[远程批量查询] G --> H{ip-api.com} H -->|成功且非未知| I[更新缓存并返回] H -->|超时/失败/未知| J{IP 版本} J -->|IPv4| K[ip2region 本地查询] J -->|IPv6| L[返回: 未知] K --> M{查询结果} M -->|成功| N[更新缓存并返回] M -->|超时/失败| L I --> O[结束] N --> O L --> O F --> O C --> O D --> O ``` ### 3.2 策略优势分析 1. **性能优先**:通过快速过滤和缓存机制,减少 90% 以上的外部查询 2. **容错能力**:远程失败时自动降级到本地查询,保证服务可用性 3. **成本控制**:本地库兜底降低对第三方 API 的依赖 4. **批量优化**:远程查询采用批量方式,减少网络开销 ### 3.3 ip2region 本地库 - **数据来源**:内嵌于二进制文件中,首次启动自动解压 - **索引优化**:加载向量索引提升查询性能 - **存储路径**:`./var/nginxpulse_data/ip2region.xdb` --- ## 4. PV 过滤机制 ### 4.1 过滤维度 PV(Page View)过滤支持三个维度的配置: | 维度 | 配置项 | 默认值 | 说明 | |------|--------|--------|------| | 状态码 | `PV_STATUS_CODES` | `[200]` | 只统计指定状态码的访问 | | URL 模式 | `PV_EXCLUDE_PATTERNS` | 内置规则 | 排除特定资源请求(如静态文件) | | IP 列表 | `PV_EXCLUDE_IPS` | 空 | 排除特定 IP 的访问 | ### 4.2 默认排除规则 项目内置了常见静态资源的排除模式: - 图片文件:`.jpg`, `.png`, `.gif`, `.ico`, `.svg` - 样式文件:`.css` - 脚本文件:`.js` - 字体文件:`.woff`, `.woff2`, `.ttf`, `.eot` --- ## 5. 部署方案 ### 5.1 单镜像容器化 NginxPulse 采用创新的单镜像设计,将前端和后端服务打包在一起: ```mermaid graph LR subgraph Docker 镜像 FRONTEND[前端静态文件<br/>/app/dist] BACKEND[后端二进制<br/>/app/nginxpulse] NGINX[Nginx 配置<br/>/etc/nginx/conf.d] end HOST[宿主机] -->|mount| LOGS[Nginx 日志目录] HOST -->|mount| DATA[数据持久化目录] FRONTEND --> NGINX BACKEND --> SQLITE[(SQLite)] LOGS --> BACKEND ``` **优势**: - 简化部署流程,只需拉取一个镜像 - 减少容器间通信开销 - 配置集中管理 ### 5.2 环境变量配置 | 变量名 | 类型 | 必填 | 默认值 | 说明 | |--------|------|------|--------|------| | `WEBSITES` | JSON | 是* | - | 网站配置(无配置文件时必填) | | `CONFIG_JSON` | JSON | 否 | - | 完整配置 JSON 字符串 | | `LOG_DEST` | string | 否 | `file` | 日志输出:`file` 或 `stdout` | | `TASK_INTERVAL` | duration | 否 | `1m` | 日志扫描间隔 | | `SERVER_PORT` | string | 否 | `:8089` | 后端服务监听地址 | | `PV_STATUS_CODES` | array | 否 | `[200]` | PV 统计状态码 | | `PV_EXCLUDE_PATTERNS` | array | 否 | 内置规则 | URL 排除模式 | | `PV_EXCLUDE_IPS` | array | 否 | 空 | IP 排除列表 | ### 5.3 持久化数据 ``` var/nginxpulse_data/ ├── nginxpulse.db # SQLite 数据库 ├── nginx_scan_state.json # 日志扫描游标 └── ip2region.xdb # IP 本地库(首次启动生成) ``` --- ## 6. 目录结构 ``` . ├── cmd/ │ └── nginxpulse/ │ └── main.go # 程序入口 ├── internal/ # 核心业务逻辑 │ ├── app/ │ │ └── app.go # 应用初始化、依赖注入 │ ├── analytics/ # 统计口径与聚合逻辑 │ ├── enrich/ │ │ ├── ip_geo.go # IP 归属地查询(远程+本地) │ │ └── pv_filter.go # PV 过滤规则实现 │ ├── ingest/ │ │ └── log_parser.go # 日志扫描与解析 │ ├── server/ │ │ └── http.go # HTTP 服务与中间件 │ ├── store/ │ │ └── repository.go # SQLite 数据访问层 │ └── web/ │ └── handler.go # API 路由处理器 ├── webapp/ # 前端项目 │ └── src/ │ └── main.ts # Vue 应用入口 ├── configs/ │ ├── nginxpulse_config.json # 主配置文件 │ └── nginx_frontend.conf # 内置 Nginx 配置 ├── scripts/ │ └── dev_local.sh # 本地开发启动脚本 ├── var/ # 运行时数据目录 ├── Dockerfile └── docker-compose.yml ``` --- ## 7. 二次开发指南 ### 7.1 环境准备 - Go 1.23.x - Node.js 20+ / npm - Docker(可选) ### 7.2 Nginx 日志格式适配 默认解析器支持以下格式: ``` <ip> - <user> [time] "METHOD /path HTTP/1.x" status bytes "referer" "ua" ``` 若使用自定义 `log_format`,需修改 `internal/ingest/log_parser.go` 中的正则表达式。 ### 7.3 扩展建议 **统计口径扩展**:修改 `internal/analytics/` **API 扩展**:在 `internal/web/handler.go` 添加新路由 **数据模型扩展**:修改 `internal/store/repository.go` 中的表结构 --- ## 8. 技术亮点总结 1. **分层缓存策略**:快速过滤 → 内存缓存 → 远程批量 → 本地兜底,平衡性能与成本 2. **轻量级架构**:SQLite + 单镜像部署,降低运维复杂度 3. **增量解析**:基于游标的日志扫描,避免重复处理 4. **容错设计**:远程 API 失败时自动降级到本地查询 5. **灵活配置**:支持配置文件和环境变量两种方式 6. **前后端分离**:Vue 3 + Go,便于独立迭代 --- ## 9. 潜在改进方向 1. **分布式支持**:当前为单机部署,可考虑支持多节点数据聚合 2. **告警功能**:增加异常访问告警(如某 IP 短时间大量请求) 3. **数据导出**:支持统计数据的报表导出 4. **更多日志格式**:支持 Apache、Caddy 等 Web 服务器日志 5. **实时性提升**:采用 inotify 替代定时扫描,实现准实时处理 --- ## 参考文献 - 项目地址:https://github.com/likaia/nginxpulse - ip2region 项目:https://github.com/lionsoul2014/ip2region - ip-api.com:https://ip-api.com/ 最后修改:2026 年 01 月 13 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏