要精确记录HTTP请求的网络带宽流量,必须启用mod_logio模块并验证其加载成功,再在每个VirtualHost中定义含%I和%O的专属日志格式,绑定独立日志路径,其中%O代表服务器实际发出的响应字节数,是真实带宽统计的核心依据。

要在 Apache 中通过 mod_logio 记录每个 HTTP 请求消耗的**精确网络带宽流量**,关键不是“打开模块”就完事,而是确保日志能真实反映服务器 socket 层实际收发的字节数——也就是客户端发来的原始请求量(%I)和服务器实际发出的响应量(%O),二者单位均为字节,无压缩、无省略、可直接用于带宽统计。
确认 mod_logio 模块已真正启用
很多配置失败的根源是模块根本没加载:%I 和 %O 在日志中显示为破折号(-),不是格式写错了,而是功能不可用。
- 运行
apache2ctl -M | grep logio(Debian/Ubuntu)或httpd -M | grep logio(RHEL/CentOS),输出必须含logio_module (shared) - 若无结果:Debian 系执行
a2enmod logio && systemctl reload apache2;RHEL 系编辑/etc/httpd/conf/httpd.conf,取消#LoadModule logio_module modules/mod_logio.so的注释,再重载服务 - 注意:
mod_log_config必须同时启用(它默认开启),否则 Apache 启动会报错
为每个虚拟主机单独定义带宽日志格式
不能复用 common 或 combined 格式——它们不含 %I/%O,也无法隔离站点数据。必须在 块内显式定义专属格式:
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 推荐写法(放入对应站点的 VirtualHost 配置中):
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" vhost_bandwidth - %I 是客户端发来的完整 HTTP 请求原始字节数(含请求行、所有头、CRLF、请求体、chunked 分隔符等)
- %O 是 Apache 调用
send()实际发出的响应总字节数(含响应头、压缩后响应体、chunked 编码分隔符、代理追加头如X-Forwarded-For等) - 二者均为纯整数,无逗号、无单位,适合脚本(如
awk '{sum += $12}')直接累加
绑定独立日志路径并启用 per-vhost 统计
同一个 Apache 实例下多个站点必须使用不同日志文件,否则带宽数据混杂、无法归因:
- 在相同
块中添加:CustomLog /var/log/apache2/site-a-access.log vhost_bandwidthErrorLog /var/log/apache2/site-a-error.log - 每个站点用唯一路径(如
site-b-access.log),确保 Apache 进程对目录有写权限(如chown root:www-data /var/log/apache2/ && chmod 755 /var/log/apache2/) - 无需额外配置
LogIOTrackInput/Output或LogIOTrackTTFB—— 这些控制内部指标采集,不影响 %I/%O 记录
理解 %O 才是真实“发出带宽”的核心依据
%O 不等于 Content-Length,也不等于浏览器最终接收量,但它是服务器侧最贴近“真实发出带宽”的指标:
- 启用
mod_deflate时,%O = 压缩后体积;静态文件未压缩时,%O ≈ 文件原始大小 - 走
mod_proxy或 FastCGI 时,%O 包含后端追加的响应头和 chunked 分隔符,比 %b 更真实 - HTTPS 流量中,%O 是 TLS 加密前的明文响应大小,%I 是解密后的明文请求大小
- 客户端中断连接(如关闭浏览器)、超时或流式响应未结束时,%O 记录的是日志写入时刻已发出的字节数,不会回填










