一、引言
在传统的 HTTP 日志中,每个请求都会被单独记录,这对于短连接、异步加载等场景非常直观;但在一些需要以“会话”为单位分析用户行为的场景下,如视频点播、多资源并行加载、长轮询等,单个请求日志难以准确反映用户整个会话的生命周期和流量消耗。
ngx_http_session_log_module
模块(商业订阅)针对这一需求推出:它可以将多个请求聚合为一个会话,待会话结束后一次写入日志,方便统计和分析。下面将以零基础、逐步演示的方式,带你掌握该模块。
二、先决条件
- NGINX 商业版:确认已包含
ngx_http_session_log_module
。 - Linux 环境(Ubuntu/CentOS 等),拥有
sudo
权限。 - 配置与重载命令:会使用
nginx -t
、systemctl reload nginx
。
三、模块验证
在终端执行:
nginx -V 2>&1 | grep --color session_log
- 若输出包含
--with-http_session_log_module
或session_log
,说明模块可用。 - 否则需联系供应商或重新编译 NGINX(添加
--add-module=.../ngx_http_session_log_module
)。
四、核心指令详解
4.1 session_log_zone
session_log_zone /path/to/logzone=name:size[format=format_name][timeout=time][id=var][md5=expr];
/path/to/log
:会话日志文件路径。zone=name:size
:定义共享内存区name
及大小(如1m
)。format=format_name
(可选):引用由session_log_format
定义的格式,默认使用内置的combined
。timeout=time
(可选,默认 30s):自上一次请求起经过该时间则认为会话结束并写日志。id=var
(可选):如果来自客户端的var
(例如 Cookie)是有效的 MD5,会直接作为会话 ID。md5=expr
:当id
不指定或无效时,基于expr
(可由多个变量拼接)计算 MD5 作为新会话 ID。
关键点:同一个会话下的所有请求,在 timeout
时间窗口内都归为同一次日志;超时后才写入并重启新会话。
4.2 session_log_format
session_log_format name string ...;
- name:格式名称,用于
session_log_zone
的format=
参数。 - string:日志模板,支持所有标准 HTTP 变量,以及
$body_bytes_sent
会话内累积值,其他变量取首个请求的值。
常见内置变量:
变量 | 含义 |
---|---|
$session_log_id | 会话 ID(16 字节二进制或 32 字符十六进制) |
$remote_addr | 首次请求时的客户端 IP |
$http_user_agent | 用户代理 |
$session_time | 会话总时长(从首次请求到最后一次请求完成计时) |
$body_bytes_sent | 会话内所有请求的响应体字节数总和 |
$request | 首次请求的请求行(如 GET /index.html HTTP/1.1 ) |
4.3 session_log
session_log name | off;
- name:启用对应
session_log_zone
中定义的会话日志。 - off:关闭当前级别继承的会话日志。
可在 http
、server
或 location
级别使用。
五、一步步配置示例
下面我们以“客户端 IP + User-Agent”作为会话标识,统计 /media/
路径下所有请求的会话日志。
5.1 创建持久化目录
sudo mkdir -p /var/log/nginx/session
sudo chown nginx:nginx /var/log/nginx/session
5.2 在 http
块中定义会话日志区
编辑 /etc/nginx/nginx.conf
,在 http { ... }
内添加:
# 定义会话日志区,1MB 大小,30s 超时,会话结束写入 /var/log/nginx/session/media.log
# 会话格式使用默认 combined,也可自定义
session_log_zone /var/log/nginx/session/media.logzone=media_zone:1mtimeout=30smd5=$binary_remote_addr$http_user_agent;
5.3 自定义日志格式(可选)
如需记录更多字段,可在 http
块继续添加:
session_log_format media_fmt '$session_log_id ''$remote_addr [$time_local] ''"$http_user_agent" ''bytes_sent=$body_bytes_sent ''session_time=$session_time';
然后在 session_log_zone
中加上 format=media_fmt
。
5.4 在 server/location
启用
server {listen 80;server_name example.com;location /media/ {# 开启会话级日志session_log media_zone;}# 其他路径不记录
}
5.5 检查与重载
sudo nginx -t && sudo systemctl reload nginx
六、验证与测试
-
模拟会话
在浏览器或命令行中多次请求同一资源,确保连续请求间隔小于 30s:curl http://example.com/media/video1.ts sleep 5 curl http://example.com/media/video2.ts
-
查看日志
tail -n20 /var/log/nginx/session/media.log
你将看到类似:
5f2d3a4b... 192.168.1.10 [12/May/2025:14:00:00 +0800] "Mozilla/5.0 ..." bytes_sent=1048576 session_time=5.123
其中:
- 第一列 为会话 ID;
- bytes_sent 为两次请求的累计发送字节;
- session_time 为首次到最后一次请求的时长。
七、典型应用场景
- 流媒体点播统计
聚合一次完整的视频播放会话(多个分片请求),统计总流量与观看时长。 - 长轮询/Comet 会话
将多次心跳/推送请求归为一次会话,评估用户在线时长。 - API 批量操作
若客户端将多次批量操作拆分为多请求,可按会话统计请求总量与数据大小。
八、进阶配置与优化
-
调整
timeout
- 对于长连接、心跳场景,可将
timeout
设置更高(如5m
)。
- 对于长连接、心跳场景,可将
-
指定
id
参数- 若前端通过 Cookie 提供稳定会话 ID,可写
id=$cookie_sessionid
,避免重复新建。
- 若前端通过 Cookie 提供稳定会话 ID,可写
-
日志轮转
- 配合
logrotate
工具定期切割/var/log/nginx/session/*.log
,防止磁盘占满。
- 配合
-
性能监控
- 监控共享内存使用情况,若活跃会话数极多,可增大
zone=size
。
- 监控共享内存使用情况,若活跃会话数极多,可增大
九、常见问题与排查
问题 | 排查建议 |
---|---|
日志文件未生成 | - 确认 session_log_zone 路径可写,且 nginx 进程用户对目录有写权限。- 检查 session_log 是否已在对应 location 启用。 |
会话聚合不生效 | - 请求间隔需小于 timeout 。- md5 表达式要包含能唯一标识会话的变量。 |
日志格式缺少字段 | - 自定义 session_log_format 时,确保使用 $body_bytes_sent 而非 $bytes_sent 。 |
共享内存不足 | - 增加 zone=...:size 中的 size ,如 2m 、4m 。 |
十、总结
通过 ngx_http_session_log_module
,你可以:
- 以会话级别代替请求级日志,直观统计用户完整交互。
- 聚合流量与时长,方便流媒体、长轮询、批量 API 等场景分析。
- 灵活配置超时、格式、ID 源,满足各种业务需求。
掌握以上配置与调优方法后,即可在 NGINX 层为复杂 HTTP 会话提供精准、连贯的日志记录,助力业务监控与数据分析。祝你上手顺利,灵活运维!