https://nginx.org/en/docs/stream/ngx_stream_log_module.html
ngx_stream_log_module
概述ngx_stream_log_module
是 NGINX 中的一个模块,用于记录通过流式(TCP/UDP)代理的连接和数据传输。它允许配置日志格式和记录日志文件的位置,以便于监控和调试流式服务的请求和响应。
ngx_stream_log_module
提供了几个主要指令,用于设置日志记录的各种参数:
log_format:
用于定义日志的格式。
语法: log_format <name> <format> [escape=default|json|none];
示例:
log_format main '$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time';
access_log:
指定日志文件的位置和使用的日志格式。
语法: access_log <path> [format [buffer=size [flush=time]] [if=condition]];
示例:
access_log /var/log/nginx/stream_access.log main;
下面是一个完整的配置示例,展示了如何配置 ngx_stream_log_module
来记录流式服务的日志:
stream {
log_format main '$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time';
access_log /var/log/nginx/stream_access.log main;
server {
listen 12345;
proxy_pass backend_server;
}
}
在这个配置中:
log_format
定义了一个名为 main
的日志格式,记录了客户端地址、时间、协议、状态、发送和接收的字节数以及会话时间。access_log
指定了日志文件的位置 /var/log/nginx/stream_access.log
,并使用 main
日志格式记录日志。server
区块定义了一个监听在端口 12345 的服务器,将流量代理到 backend_server
。可以通过在 log_format
指令中使用内置变量来定制日志格式。常用的内置变量包括:
$remote_addr
: 客户端地址。$time_local
: 本地时间。$protocol
: 使用的协议。$status
: 请求状态。$bytes_sent
: 发送的字节数。$bytes_received
: 接收的字节数。$session_time
: 会话持续时间。例如,要添加更多的细节到日志中,可以这样做:
log_format detailed '$remote_addr - [$time_local] "$protocol" $status '
'sent:$bytes_sent received:$bytes_received time:$session_time '
'"$upstream_addr" "$upstream_bytes_sent" "$upstream_bytes_received"';
这会记录更多关于上游服务器的信息以及发送和接收的数据量。
继续之前的基础配置介绍,ngx_stream_log_module
还支持一些高级功能,比如日志条件和缓冲区配置,这些功能可以帮助更精细地控制日志记录。
日志条件允许根据特定条件记录日志。这通过 access_log
指令的 if
参数实现。条件可以使用 NGINX 变量来定义,只有在条件为真时才会记录日志。
语法: access_log <path> [format [buffer=size [flush=time]] [if=condition]];
示例:
stream {
log_format main '$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time';
# 仅当客户端地址为特定 IP 时记录日志
access_log /var/log/nginx/stream_access.log main if=$remote_addr ~ '192.168.1.1';
server {
listen 12345;
proxy_pass backend_server;
}
}
在上述配置中,只有当客户端地址是 192.168.1.1
时才会记录日志。
缓冲区配置可以提高日志记录性能,特别是在高负载的环境下。通过使用 buffer
和 flush
参数,日志可以首先写入缓冲区,然后在适当的时候刷新到磁盘。
语法: access_log <path> [format [buffer=size [flush=time]] [if=condition]];
示例:
stream {
log_format main '$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time';
# 配置缓冲区大小和刷新时间
access_log /var/log/nginx/stream_access.log main buffer=32k flush=5s;
server {
listen 12345;
proxy_pass backend_server;
}
}
在这个配置中:
buffer=32k
设置缓冲区大小为 32KB。flush=5s
设置每 5 秒刷新一次缓冲区。以下是一个结合日志条件和缓冲区配置的综合示例:
stream {
log_format main '$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time';
# 仅记录成功的会话并使用缓冲区配置
access_log /var/log/nginx/stream_access.log main buffer=16k flush=10s if=$status = 200;
server {
listen 12345;
proxy_pass backend_server;
}
}
在这个配置中:
200
(成功)的日志才会被记录。要在 Nginx 的 stream 模块中增加日志记录,以记录请求 IP 和请求时间等详细信息,可以按照以下最佳实践进行配置:
打开 Nginx 配置文件:
通常,Nginx 的主配置文件位于 /etc/nginx/nginx.conf
。你也可以在特定的 stream 配置文件中进行设置。
定义日志格式:
使用 log_format
指令定义日志格式。可以包括请求 IP、请求时间、协议、状态、发送和接收的字节数等信息。例如:
stream {
log_format detailed '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time $upstream_addr '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
}
设置访问日志:
使用 access_log
指令指定日志文件的位置和使用的日志格式。例如:
stream {
access_log /var/log/nginx/stream-access.log detailed buffer=32k flush=5s;
}
启用日志缓冲:
为了优化日志记录性能,可以启用日志缓冲。使用 buffer
参数指定缓冲区大小,使用 flush
参数指定刷新间隔。例如:
stream {
access_log /var/log/nginx/stream-access.log detailed buffer=32k flush=5s;
}
重启 Nginx: 修改配置文件后,重启 Nginx 以使更改生效:
sudo systemctl restart nginx
以下是一个完整的示例配置,展示了如何在 Nginx 的 stream 模块中记录详细的请求信息:
stream {
upstream socket_proxy {
hash $remote_addr consistent;
# 转发的目的地址和端口
server 127.0.0.1:5002;
}
server {
listen 5001;
proxy_connect_timeout 600s;
proxy_timeout 600s;
proxy_pass socket_proxy;
}
log_format detailed '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time $upstream_addr '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
# logs目录下
access_log logs/stream-access.log detailed buffer=32k flush=5s;
}
Nginx 的 stream
模块可以用于记录 TCP 和 UDP 流量。日志格式由各种变量组成,每个变量代表请求处理过程中的一个特定信息。
log_format detailed '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time $upstream_addr '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
$remote_addr
:
[$time_local]
:
[10/May/2024:15:05:06 +0000]
。$protocol
:
$status
:
$bytes_sent
:
$bytes_received
:
$session_time
:
$upstream_addr
:
"$upstream_bytes_sent"
:
"$upstream_bytes_received"
:
"$upstream_connect_time"
:
Nginx 的 access_log
指令用于配置访问日志的记录方式及相关选项。在 stream
模块中,这条指令可以记录 TCP 和 UDP 连接的日志信息。
access_log logs/stream-access.log detailed buffer=32k flush=5s;
access_log
:
logs/stream-access.log
:
logs/stream-access.log
文件中。detailed
:
log_format
格式,这里使用的是名为 detailed
的日志格式。在 log_format detailed ...
中定义了具体格式。buffer=32k
:
flush=5s
:
logs/stream-access.log
)或者绝对路径,取决于你配置文件的具体位置和服务器的目录结构。log_format
指令中预先定义的格式名 detailed
,该格式包含了具体的日志记录变量和格式。172.168.20.20
在 2024 年 5 月 16 日 21:09:19(UTC+8)发起了一个 TCP 请求。200
。154764
字节,并从客户端接收 1518
字节。23.700
秒。10.11.211.35:15002
。1518
字节,并从上游服务器接收 154764
字节。0.001
秒。在 stream
块中使用 map
指令定义一个变量来存储当前日期,用于构建日志文件名。
stream {
upstream socket_proxy {
hash $remote_addr consistent;
# 转发的目的地址和端口
server 127.0.0.1:5002;
}
server {
listen 5001;
proxy_connect_timeout 600s;
proxy_timeout 600s;
proxy_pass socket_proxy;
}
log_format detailed '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time $upstream_addr '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
map $time_iso8601 $logdate {
default 'date-not-found';
'~^(?<ymd>\d{4}-\d{2}-\d{2})' $ymd;
}
access_log logs/stream-access-$logdate.log detailed;
}
按天记录日志,就无法使用bufferd 选项了。
对于 buffered logs(缓冲日志),确实存在一些限制:
Nginx 官方文档明确指出,对于缓冲日志(使用 buffer
参数),日志文件名不能包含变量。这是因为缓冲日志在写入磁盘之前会先缓存在内存中,如果文件名包含变量,可能会导致多个日志写入同一个文件,从而造成日志混乱。[4]
对于非缓冲日志(没有使用 buffer
参数),Nginx 允许在日志文件名中使用变量,比如您之前提到的 $logdate
变量。这样可以实现按天自动创建新的日志文件。
因此,如果想要按天存储访问日志,并且使用 $logdate
变量作为日志文件名,需要将访问日志配置为非缓冲日志,即不使用 buffer
参数。示例配置:
http {
# 定义日期变量
map $time_iso8601 $logdate { ... }
# 非缓冲访问日志
access_log /var/log/nginx/access-$logdate.log main;
# ...
}
这样就可以避免使用变量作为缓冲日志文件名的错误,并实现按天存储访问日志的目的。
[1] http://nginx.org/en/docs/stream/ngx_stream_log_module.html [2] https://serverfault.com/questions/916653/what-is-the-default-log-format-on-nginx [3] https://docs.nginx.com/nginx/admin-guide/monitoring/logging/ [4] https://www.nginx.com/blog/diagnostic-logging-nginx-javascript-module/ [5] https://webdock.io/en/docs/mastering-web-fundamentals/web-server-setup-management/nginx-logs-step-step-configuration-guide [6] https://stackoverflow.com/questions/42083611/how-to-make-nginx-print-full-log-for-tcp-stream [7] https://signoz.io/blog/nginx-logging/ [8] https://www.digitalocean.com/community/tutorials/how-to-add-the-log-module-to-nginx-on-ubuntu-16-04 [9] https://sematext.com/blog/nginx-logs/ [10] https://www.nginx.com/blog/rate-limiting-nginx/ [11] https://betterstack.com/community/guides/logging/how-to-view-and-configure-nginx-access-and-error-logs/ [12] https://www.digitalocean.com/community/tutorials/nginx-access-logs-error-logs [13] https://gist.github.com/tuxity/bf52447fa393c40114210d7f6d623015 [14] http://nginx.org/en/docs/http/ngx_http_log_module.html [15] https://wenvpn.com/devops/web/nginx/how-to-record-full-url-in-nginx-log-a-guide-for-improved-tracking/