一、背景介绍
在现代网络架构中,Nginx 作为一款高性能的 Web 服务器和反向代理服务器,广泛应用于各种场景。除了对 HTTP/HTTPS 协议的出色支持,Nginx 从 1.9.0 版本开始引入了对 TCP 和 UDP 协议的代理功能,这使得它在处理数据库连接代理、流媒体服务代理等 TCP 相关业务场景中也发挥着重要作用。
在 TCP 代理场景下,准确、详细的日志记录对于监控服务运行状态、排查故障、分析业务流量等工作至关重要。通过合理配置 Nginx 的 TCP 日志输出,运维人员和开发人员能够获取到丰富的信息,如客户端连接来源、后端服务器响应情况、数据传输量等,从而为系统的稳定运行和优化提供有力支持。
二、原理剖析
Nginx 的 TCP 日志输出依赖于其内部的日志模块,在 TCP 代理过程中,当客户端与 Nginx 建立连接,Nginx 再与后端服务器建立连接并进行数据转发时,日志模块会在不同阶段收集各种相关信息。这些信息包括但不限于连接的源地址和目标地址、协议类型、连接状态、数据传输的字节数等。
根据配置的日志格式和规则,日志模块将收集到的信息进行格式化处理,并在适当的时机将日志写入到指定的文件中。默认情况下,Nginx 会在 TCP 连接断开时完成日志记录并写入文件,以减少频繁的磁盘 I/O 操作对性能的影响。然而,通过一些配置调整,我们可以改变日志记录的时机和方式,使其更符合业务需求。
三、详细配置步骤
3.1 确认 Nginx 支持 stream 模块
在进行 TCP 日志配置前,首先要确保 Nginx 已启用stream模块。如果在启动 Nginx 时出现nginx: [emerg] unknown directive "stream"错误,说明 Nginx 在编译时未包含该模块。可以通过重新编译 Nginx 并添加–with-stream选项来解决,或者使用包管理器安装支持stream模块的 Nginx 版本(不同系统的包管理器操作有所不同,如在 Ubuntu 中可尝试安装nginx-stream-module相关包)。
3.2 配置日志格式
在 Nginx 配置文件中,一般在stream模块内定义日志格式。例如:
stream {log_format tcp_log '$remote_addr - $upstream_addr - [$time_local] ''$protocol $status $bytes_sent $bytes_received';...
}
在上述配置中:
- $remote_addr表示客户端的 IP 地址。
- $upstream_addr是后端服务器的地址。
- $time_local为本地时间。
- $protocol指使用的协议(如 TCP)。
- $status表示连接状态。
- b y t e s s e n t 和 bytes_sent和 bytessent和bytes_received分别是发送给客户端和从客户端接收的字节数。
3.3 配置访问日志
配置好日志格式后,需要指定日志文件路径以及使用的日志格式。例如:
stream {...access_log /opt/app/nginx/log/doris-proxy.log tcp_log buffer=32k flush=5m;
}
这里,/opt/app/nginx/log/doris-proxy.log是日志文件路径。tcp_log是前面定义的日志格式名称。buffer=32k设置了日志缓冲区大小为 32KB,以减少磁盘 I/O 次数。flush=5m表示每 5 分钟将缓冲区中的日志刷新到磁盘。如果希望日志更实时地记录,可以适当减小flush的时间间隔,如flush=10s。
3.4 配置错误日志
除了访问日志,错误日志对于排查问题也非常重要。在stream模块中添加错误日志配置:
stream {...error_log /opt/app/nginx/log/doris-proxy-error.log notice;
}
/opt/app/nginx/log/doris-proxy-error.log是错误日志文件路径,notice是日志级别。可以根据实际需求调整日志级别,如debug(最详细)、info、warn、error、crit(最简略)。
3.5 配置 TCP 代理服务器并关联日志
在stream模块内配置 TCP 代理服务器,并确保每个server块中关联上述定义的日志配置。例如:
stream {...server {listen 7034;proxy_connect_timeout 300s;proxy_timeout 3880000s;proxy_pass backend_server;access_log /opt/app/nginx/log/doris-proxy.log tcp_log buffer=32k flush=5m;error_log /opt/app/nginx/log/doris-proxy-error.log notice;}
}
backend_server应替换为实际的后端服务器地址或服务器组名称。
3.6 检查配置并重启 Nginx
完成配置修改后,使用nginx -t命令检查配置文件语法是否正确。如果无误,执行sudo service nginx restart命令重启 Nginx 服务,使配置生效。
四、日志格式详解
Nginx 提供了丰富的内置变量用于日志格式定义,通过组合这些变量,可以创建满足不同需求的日志格式。除了前面提到的常用变量,还有:
- $session_time:会话持续时间,即从客户端连接到连接断开的总时长。
- $upstream_bytes_sent:发送给后端服务器的字节数。
- $upstream_bytes_received:从后端服务器接收的字节数。
- $upstream_connect_time:与后端服务器建立连接所花费的时间。
例如,以下是一个更详细的日志格式定义:
log_format detailed_tcp_log '$remote_addr [$time_local] ''$protocol $status $bytes_sent $bytes_received ''$session_time "$upstream_addr" ''"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
这种详细的日志格式能够提供更全面的信息,帮助运维人员深入分析 TCP 连接的整个生命周期和数据传输情况。
五、高级设置
5.1 日志缓存优化
Nginx 使用日志缓存来提高性能,减少磁盘 I/O 操作。除了前面提到的buffer和flush参数,还可以通过open_log_file_cache指令进一步优化日志缓存。例如:
open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;
- max:指定缓存中最多可以存储的日志文件描述符数量。
- inactive:设置在多长时间内(这里是 20 秒),如果一个日志文件描述符没有被使用,就会从缓存中移除。
- valid:表示每隔 1 分钟检查一次缓存中日志文件的状态,确保其有效性。
- min_uses:规定一个日志文件描述符至少被使用 2 次后才会被缓存。
5.2 日志轮转
随着时间的推移,日志文件会不断增大,为了管理日志文件大小并保留历史日志,需要进行日志轮转。在类 Unix 系统中,通常使用logrotate工具来实现。例如,在/etc/logrotate.d/目录下创建一个针对 Nginx TCP 日志的配置文件,内容如下:
/opt/app/nginx/log/doris-proxy.log {dailymissingokrotate 7compressdelaycompressnotifemptycreate 640 nginx nginxsharedscriptspostrotate/usr/sbin/nginx -s reopenendscript
}
上述配置表示:
- daily:每天进行一次日志轮转。
- missingok:如果日志文件不存在,不报错继续执行。
- rotate 7:保留 7 天的日志文件,旧的日志文件将被删除。
- compress:对轮转后的日志文件进行压缩。
- delaycompress:延迟压缩,在下一次轮转时压缩上一次轮转的日志文件。
- notifempty:如果日志文件为空,不进行轮转。
- create 640 nginx nginx:轮转后创建新的日志文件,权限为 640,所有者和组为nginx。
- sharedscripts:只在所有日志文件都轮转后执行一次脚本。
- postrotate和endscript之间的命令/usr/sbin/nginx -s reopen:通知 Nginx 重新打开日志文件,以便将新的日志写入新文件。
5.3 基于条件的日志记录
在某些情况下,可能希望只记录特定条件下的 TCP 连接日志。例如,只记录与特定后端服务器通信的日志,或者只记录传输字节数超过一定阈值的日志。虽然 Nginx 原生的 TCP 日志模块没有像 HTTP 模块那样强大的条件日志功能,但可以通过一些第三方模块(如nginx-sticky-module-ng)或结合日志收集工具(如logstash、fluentd)来实现。
例如,使用logstash可以在日志收集阶段对 Nginx TCP 日志进行过滤和处理。在logstash的配置文件中,可以编写如下规则:
input {file {path => "/opt/app/nginx/log/doris-proxy.log"start_position => "beginning"}
}
filter {if [message] =~ /192.168.1.100/ {# 只处理与IP为192.168.1.100的后端服务器相关的日志}
}
output {elasticsearch {hosts => ["localhost:9200"]index => "nginx_tcp_logs"}
}
通过这种方式,可以实现更灵活、更有针对性的日志记录和处理。
通过对 Nginx TCP 日志输出的深入理解和合理配置,能够更好地监控和管理基于 TCP 协议的服务,为系统的稳定运行和优化提供有力支持。希望本文所介绍的内容能帮助读者在实际工作中充分利用 Nginx 的日志功能,提升系统运维和开发的效率。nginx官网详细配置