大家好,我是 WeiyiGeek,一名深耕安全运维开发(SecOpsDev)领域的技术从业者,致力于探索DevOps与安全的融合(DevSecOps),自动化运维工具开发与实践,企业网络安全防护,欢迎各位道友一起学习交流、一起进步 ,若此文对你有帮助,一定记得点个关注⭐与小红星❤️或加入到作者知识星球『 全栈工程师修炼指南』,转发收藏学习不迷路 。
温馨提示:若文章代码块中存在乱码或不能复制,请联系作者,也可通过文末的阅读原文链接,加入知识星球中阅读,原文链接:https://articles.zsxq.com/id_713d6lwet0zc.html
1.4 磁盘IO性能优化
首先是从硬件层面,其次使用内存替代磁盘访问,例如,当需要做性能统计时,以及使用 ngx_http_empty_gif_module 避免磁盘文件读取,它的主要功能是生成一个 1×1 透明的 GIF 图片,所以当你的网站需要返回一个空的 GIF 图片时(例如,用于占位符、透明图片等),将图片直接构造于内存;另外还可从优化读取(例如:使用 sendfile 零拷贝技术),减少写入(关闭不必要日志记录,还可将日志直接传递到 syslog 服务器中),以及使用线程池(Thread Pool)来消除磁盘IO。
主要关注系统硬盘的读(Read)、写(Write)、随机(Random)、顺序(Sequential)、IOPS(每秒输入输出操作次数)和 BPS(每秒传输的字节数),可通过 iostat 命令查看,并使用 dd 测试硬盘性能;建议使用 SSD 磁盘,其随机IO性能远优于 HDD ,但是需注意其寿命问题,另外,影响硬盘性能的因素包括如下:
- • 软件因素
1. I/O 模式
- 随机 vs 顺序
- 读 vs 写比例
2. 块大小 (Block Size)
- 小块 (4K): 高 IOPS,低吞吐
- 大块 (1M): 低 IOPS,高吞吐
3. 文件系统
- ext4: 通用稳定
- XFS: 大文件优化
- ZFS/Btrfs: 高级特性
4. RAID 级别
- RAID 0: 性能最高,无冗余
- RAID 1: 写性能下降,读性能提升
- RAID 5/6: 写惩罚显著
- RAID 10: 最佳性能+冗余
- • 硬件方面
1. 存储介质
- HDD: 受限于机械臂和盘片转速,价格低、存储大、寿命长,但随机IO性能差,适用于顺序读写密集型应用,如数据库、日志存储等
- SSD: 受限于闪存类型和控制器,价格高、延迟低、写寿命短,随机IO性能好,适用于高并发读写密集型应用,如Web服务器、缓存服务
2. 接口带宽
- SATA III: 600 MB/s (6 Gbps)
- SAS 12G: 1200 MB/s
- PCIe 4.0 x4: 8 GB/s
- PCIe 5.0 x4: 16 GB/s
3. 队列深度 (Queue Depth)
- 深度越大,并行处理能力越强
- HDD: QD1-32
- SSD: QD1-256+
温馨提示: 对于顺序读写以及随机读写,可分别对应参照 BPS 和 IOPS 指标,并结合实际业务场景进行选择。
在讲解磁盘性能优化之前,我们先来学习一下磁盘中一些概念,例如直接IO、异步IO等,以及它们各自的优缺点。
- • 1.直接 IO 绕开磁盘高速缓存,直接与磁盘交互,适用于大文件传输场景。
常规IO读写操作,会将磁盘数据先加载到内核缓冲区,然后再拷贝到用户空间,相当于拷贝了两次,这是其缺点,优点当文件不超过缓冲区大小,并应读到缓冲区时,如果下载再读,就命中到同一个缓冲区的内容,就不需要从磁盘读取了。
直接IO读写操作,优点是减少了内核空间到用户空间的拷贝次数,提升了效率;缺点是数据的一致性无法保证,且在高并发场景下可能会成为瓶颈。
常规与直接IO流程区别图
- • 2.异步 IO 使用 Liunx 提供原生的 AIO 方法。
常规IO读写操作,用户空间发起一个read调用,然后用户空间这边就会被阻塞,同时用户进程也被阻塞住,然后开始去读磁盘,读到高速缓冲区,然后读到用户缓冲区,读完之后再唤醒进程,这个过程是阻塞的,然后用户进程再进行其它的一些操作;
其次写的时候也是一样的,由于写的时候往往磁盘高速缓冲区(
写入快),然后再写入磁盘的。 异步IO读写操作,当用户空间发起一个read调用之后,用户进程并不会被阻塞,而是继续执行其它的一些操作,然后内核这边会去读磁盘,读完之后再唤醒用户进程,这个过程是非阻塞的,写的时候也是一样的,由于有磁盘高速缓存,写的时候往往磁盘高速缓冲区(写入快),这是一个脏页可用循环写入(不会被阻塞)再写入磁盘的
常规与异步IO流程区别图
优化指南
适用于大文件传输的直接IO功能开启指令
描述:当磁盘上文件大小超过内存缓冲区时,可启用 Direct IO (直接IO),避免 Buffered IO 模式下磁盘页缓存中的拷贝消耗,提升效率。
例如,原始视频文件或归档文件,每个文件都将近几个G的大小,它不太可能在我们的内存中缓存,那么每次读取都是一个浪费,这种情况下启用直接IO是非常合适的,避免了读一次还要拷贝一次的这样消耗。
在 Nginx 中提供了 directio 与 directio_alignment 指令,用以开启直接IO模式,指令参数:
• directio : 在读取大于或等于指定大小的文件时,启用 O_DIRECT 标志(FreeBSD、Linux)、F_NOACHE 标志(macOS)或directio()函数(Solaris)或者在Linux 中使用 aio,缺省是关闭的。
Syntax: directio size | off;
Default: directio off;
Context: http, server, location
• directio_alignment: 设置直接IO的对齐大小,默认为512字节。在大多数情况缺省对齐值就足够了,若在 Linux 下使用XFS分区时,需要将其增加到4K。
Syntax: directio_alignment size;
Default: directio_alignment 512;
Context: http, server, location
适用于高并发场景的异步IO功能开启指令
描述:在高并发的场景下,可启用 AIO (异步IO),避免阻塞等待磁盘操作完成,提升效率,其指令参数:
aio : 是否开启异步IO, 在 Linux 上 AIO 可以从内核版本2.6.22开始使用,此外有必要启用 directio,否则读取将被阻止.
Syntax: aio on | off | threads[=pool];
Default: aio off;
Context:http, server, location
# 示例
# 1.在FreeBSD和Linux上启用或禁用异步文件I/O(AIO)
location /video/ {
aio on;
output_buffers 1 64k;
}
# 有必要启用directio,否则读取将被阻止
location /video/ {
aio on;
directio 512;
output_buffers 1 128k;
}
aio_write : 开启异步写操作,通常情况下没必要开起此功能,因为本身写入是到磁盘高速缓存区,不存在阻塞的情况,所以其缺省是关闭的;仅接收上游服务发来的响应时打开 proxy buffing 缓存,并把它记录到一个临时文件中,只有在这样的场景下才启用此指令。
Syntax: aio_write on | off;
Default: aio_write off;
Context: http, server, location
worker_aio_requests: 当将aio与epoll连接处理方法一起使用时,为单个工作进程设置未完成的异步I/O操作的最大数量。
Syntax: worker_aio_requests number;
Default: worker_aio_requests 32;
Context: events
温馨提示:当Linux上同时启用AIO和sendfile时,AIO用于大于或等于directio指令中指定大小的文件,而sendfile用于较小大小的文件时将禁用directio。
location /video/ {
sendfile on;
aio on;
directio 8m;
}
参考文档:https://nginx.org/en/docs/http/ngx_http_core_module.html#aio
另外,在 aio 指令中还可以使用 threads 参数来启用线程(异步读 IO 线程池);默认情况下,多线程是禁用的,应该使用 --with-threads 配置参数启用它。目前,多线程仅与 epoll 、kqueue 和 eventport 方法兼容,此外 Nginx 只有 Linux 支持多线程发送文件,Windows 不支持。
正常情况下,是在我的 Worker Process Event Cycle 事件驱动框架中反复的执行,但是有可能在某一些任务的执行,我们会认为它可能会阻塞,所以会派生一堆线程,例如下图中的三个线程,我使用了一个生产者模型,其中生产者就是 Work Process,然后生产一个 New Task ,插入到 Tasks Queue 队列中这是一个先进先出,然后消费者就是这三个线程,这三个线程会从这个队列中抢出任务来执行,在某个线程执行过程中可能会阻塞住线程,执行完毕后就会继续往下走,最后扔到 WorkSpace 中做一些非阻塞的操作,最后再回到 Work Process 中继续往下执行。
在 Nginx 中官方的所有模块都是非阻塞的,那么为啥会出现阻塞呢? 因为在 Nginx 来做静态资源时,处理过多的文件,比如说几千上万文件,那么在读取这些文件的时候,可能会导致缓存的 inode 失效,因为内存不够大,所以这个时候的就会出现阻塞,所以这个时候就需要用到线程池,从而有个9倍的性能提升(Nginx 官网博客中提及到)。
Thread Pool线程池图
所以,在 nginx 中提供的 thread_pool 指令,它仅用于我们刚才说的做静态资源服务的时候,读取文件的场景下。
• thread_pool: 定义一个线程池,默认情况下,Nginx 会创建一个名为 default 的线程池可配置到 aio 指令中使用,其中包含32个工作线程和65536个队列。
Syntax: thread_pool name threads=number [max_queue=number];
Default: thread_pool default threads=32 max_queue=65536;
Context: main
- • output_buffers: 设置用于从磁盘读取响应的缓冲区的数量和大小,主要将磁盘文件读入到缓存中处理,如 gzip 模块会使用到。
Syntax: output_buffers number size;
Default: output_buffers 2 32k;
Context: http, server, location
至此,作者介绍了磁盘 IO 优化的一些大的方向,接下来将继续介绍四种减少磁盘 IO 读取或写入次数的具体方案。
使用 empty_git 模块行为分析从内存返回响应
描述:ngx_http_empty_gif_module 模块通过内存中直接返回43字节(响应)透明GIF减少读IO,为最小化对浏览器DOM解析性能的影响,选择请求体积最小、渲染开销最低的资源——即 1×1 像素透明GIF图片,从而加快了处理速度,该模块默认编译进 Nginx,可通过--without-http_empty_gif_module 指令禁用。
其主要应用于用户行为分析场景,如在前端做用户行为分析(如页面停留时长、点击序列)时存在跨域要求,,常通过 GET 请求上报数据(埋点),响应体本身无关紧要,通过 Nginx 的 access 日志获取到请求的参数,再接入到 VictoriaLogs 或 ClickHouse 等日志存储分析软件中,进行后续的数据分析。
语法参数:
Syntax: empty_gif;
Default: —
Context: location
示例演示:
# 在 Nginx 配置文件中,添加以下内容以启用 empty_gif 功能。
location = /trace.gif {
empty_gif;
}
# 配置 ico 文件,用以解决浏览器访问不存在的 favicon.ico 文件时,返回404错误的问题。
location = /favicon.ico {
empty_gif;
log_not_found off;
access_log off;
expires max;
}
使用 access.log 日志压缩和缓存及轮转
描述:在 Nginx 中提供了强大的日志记录功能,用于分析用户请求和统计相关访问数据,不仅可自定义日志格式,还可通过 gzip 压缩、buffer 缓存来减少磁盘IO,另外,还可利用 logrotate 工具进行日志轮转,以避免单个文件过大导致磁盘IO过高。
指令参数:
- • access_log: 设置缓冲日志写入的路径、格式和配置。
Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default: access_log logs/access.log combined;
Context: http, server, location, ifin location, limit_except
# 参数说明: 设置缓冲日志写入的路径、格式
# path: 日志文件的路径,可以是绝对路径或相对路径。
# buffer: 日志写入缓冲区的大小,默认为 64k。(优先级高)
# format: 日志的格式,可以是预定义的格式(如 combined),也可以是自定义格式。
# flush: 日志写入磁盘的频率,默认为 30s。(优先级次之)
# if: 条件表达式,用于控制日志记录的条件。
# 使用示例
## 本地记录
log_format compression '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"';
access_log /var/log/nginx/access.log compression buffer=32k;
## syslog 记录
access_log syslog:server=192.168.10.52,facility=local7,tag=nginx,severity=info compression;
## 开启日志压缩,指定刷新写入时间,减少磁盘IO
access_log /var/log/nginx/access.log.gz combined gzip flush=5m;
log_format :设置错误日志的路径、级别和配置
Syntax: log_format name [escape=default|json|none] string ...;
Default: log_format combined "...";
Context: http
open_log_file_cache: 设置日志文件的缓存,用于存储名称包含变量的常用日志的文件描述符,减少打开和关闭文件操作的次数。
Syntax: open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
Default: open_log_file_cache off;
Context: http, server, location
# 参数说明
# max : 设置缓存中描述符的最大数量; 如果该高速缓存已满,则关闭最近最少使用(LRU)的描述符。
# inactive: 设置描述符在缓存中保持活动状态的最长时间,超过此时间将被关闭,缺省 10s。
# min_uses: 设置描述符在缓存中保持活动状态的最小次数,缺省 1 次。
# valid: 设置检查文件是否仍以相同名称存在的时间,缺省60秒 。
# off: 禁用缓存文件描述符的选项。
温馨提示:max 取值并非越大越好,通常与日志文件数量成正比(通常 50~128 即可),再变量路径时可用稍微设置大一些(1000足矣),可通过 lsof 命令查看当前 Nginx 进程打开的日志文件数量,例如:lsof -p $(cat /run/nginx.pid) | grep log | wc -l 。
打开日志文件数量图
log_subrequest: 指令控制是否在访问日志中记录子请求的日志信息,缺省情况下是关闭,生产环境下不建议开启避免在高并发场景下日志量翻倍,除非是在调试、性能分析、安全审计时临时开启。
Syntax: log_subrequest on | off;
Default: log_subrequest off;
Context: http, server, location
# 使用示例
server {
log_subrequest on;
# 定义条件日志变量
set$log_full 0;
# 例如,当请求参数中包含 debug=1 时,开启完整日志记录
if ($arg_debug = 1) {
set$log_full 1;
}
# 使用if条件控制日志记录
access_log /var/log/nginx/access_full.log main if=$log_full;
}
温馨提示:特别注意 user 指令指定了运行用户,请确保运行用户确保 Nginx 进程有权限访问日志文件目录,否则可能到 open() "/var/log/nginx/access.log" failed (13: Permission denied) 错误,可通过以下命令检查并修改权限:
# 假如:以 nginx 用户运行 Nginx,则需确保 /var/log/nginx 目录的权限允许 nginx 用户读写。
chown -R nginx:nginx /var/log/nginx
温馨提示:建议在同一个配置层级同时指定 root 和 access_log 指令,因为每次写入日志时,都会检查请求的根目录是否存在,如果该目录不存在,则不会创建日志文件。
server {
root /spool/vhost/data/$host;
access_log /spool/vhost/logs/$host;
}
示例演示:
- • 例1: 使用缓存日志文件描述符以及日志压缩和缓存,以减少磁盘IO。
http {
server {
....
# 日志文件fd缓存优化配置,减少打开和关闭文件的开销
open_log_file_cache max=128 inactive=60s min_uses=2 valid=1m;
# 缓存最多 128 个日志文件句柄;如果在 60s 内没被访问就关闭;
# 在 60s 内至少用到 2 次才会被长期缓存;每 1 分钟检查一次文件的存在性。
# 日志压缩和缓存,减少磁盘IO
# 使用 main 格式记录日志,并启用 gzip 压缩和 buffer=32k 缓存,以及 flush=5m 最大延迟写入间隔(缓存与刷新谁先满足则写入)。
access_log /var/log/nginx/access.log.gz main gzip buffer=32k flush=5m;
}
}
然后重载 Nginx 配置后,访问触发日志写入,生成的二进制压缩格式文件,可通过 zcat 命令还原为明文日志,验证时间戳与请求准确无误,这将显著减少磁盘的写操作次数和节约磁盘空间。
# 打开压缩日志文件,查看内容是否正确。
$ zcat /var/log/nginx/test-access.log.gz
# 压缩文件解压前文件大小
$ ls -alh /var/log/nginx/test-access.log.gz
-rw-r--r-- 1 root root 31k Mar 10 08:44 test-access.log.gz
# 压缩文件解压后,日志文件 207 kb,相较压缩前 31 kb,节省了jingwei近70%的空间。
$ gunzip -c /var/log/nginx/test-access.log.gz > test-access.log
$ ls -alh /var/log/nginx/test-access.log
-rw-r--r-- 1 root root 207K Mar 10 08:44 test-access.log
温馨提示:在 nginx 运行时一般不建议直接修改日志文件,可能会导致生产日志丢失,如果需要手动归档旧日志,可以使用 logrotate 等工具进行管理,确需不停机手动处理的情况(例如:移动),在容忍日志有可能丢失的情形下,可使用 /bin/kill -USR1 $(cat ./nginx.pid 2>/dev/null) 2>/dev/null || true 命令发送 USR1 信号给 Nginx 主进程,让其重新打开日志文件。
- • 例子2: 使用 map 指令和日志格式变量,根据变量条件记录不同日志,例如按天分隔,
http {
# 方式1.日志按天分隔变量定义,使用 map 模块映射 time_iso8601 变量利用元组截取年月日,并赋值给 logdate 变量(日志常用)
map $time_iso8601$logdate {
'~^(?<ymd>d{4}-d{2}-d{2})'"$ymd";
default "nodate";
}
server {
....
# 日志文件fd缓存优化配置,减少打开和关闭文件的开销
open_log_file_cache max=1000 inactive=60s min_uses=2 valid=1m;
# 日志按天分隔
access_log /var/log/nginx/access-$logdate.log main;
....
}
}
温馨提示:在日志路径中使用变量时,会导致 access_log 指令中的 buffer 与 flush 缓存选项无法使用,配置后将报 nginx: [emerg] buffered logs cannot have variables in name 错误信息。
• 例3: 使用 logrotate 工具归档日志文件按天分割,避免 Nginx 在日志路径中使用 map 指令变量导致 buffer 与 flush 缓存选项无法使用,以及在突发流量下单个日志文件过大,导致读写IO性能不佳。
以 Nginx/Openresty 为例,在 alpine 容器中配置 access 日志轮转规则如下所示。
步骤 01. 创建 logrotate 的配置文件,如下所示。
步骤 02.创建 Dockerfile 文件,添加 logrotate 以及配置文件以支持日志轮转。
温馨提示:作者在 Alpine 镜像中使用了 adduser 来创建 nginx 用户用于 Worker 的执行,而不是使用 root 用户。这样可以提高安全性并减少潜在的安全风险;另外,指定了定时任务在每天凌晨进行轮转,轮转的日期以前一天的日期命名。
步骤 03. 运行创建容器,如下所示,注意需要在 Nginx 配置中指定日志文件的路径为 /var/log/nginx/vhost/ 以及 nginx pid 文件路径为 /run/nginx.pid。
温馨提示:由于 alpine 精简镜像没有后台自动 crond 服务,所以需要在容器启动时手动运行 crond -b 来启动后台运行的定时任务,以便于在凌晨时进行日志轮转。
步骤 04.执行并查看日志轮转情况,当文件大于 200MB 时轮转或者 crond 定时轮转,如下所示。
# 手动执行日志轮转命令
$ /usr/sbin/logrotate -f -s /var/log/nginx/vhost/logrotate.status /etc/logrotate.conf
# 测试效果
$ ls -alh /var/log/nginx/vhost
total 133K
-rw-r----- 1 root root 118 Mar 12 11:10 logrotate.status
-rw-rw-r-- 1 nginx root 12.8K Mar 12 11:14 www.log
-rw-r--r-- 1 root root 4.5K Mar 12 11:10 www.log_20260312_111048.gz
-rw-rw-r-- 1 nginx root 16.6K Mar 12 11:11 www.log_20260312_111232
至此,access 日志按天分割,也可使用缓存刷新机制了。
- • 例4: 使用 syslog 协议网络传输日志到日志服务器,以减少服务器磁盘IO。
作者之前发布一篇《等保合规 | Rsyslog 高阶玩法:审计日志平移直通 VictoriaLogs 实践指南》文章,详细介绍了如何使用在 Linux 中搭建部署使用 syslog 协议传输日志到日志服务器,这里就再简单的回顾一下以及如何在 Nginx 中配置使用 syslog 协议传输日志到日志服务器。
syslog 是一种广泛使用的日志传输协议,它允许你将应用程序的日志信息通过网络发送到远程服务器进行集中存储和处理,它有两种标准 RFC 5424 和 RFC 3164,RFC 5424 是最新的标准,它提供了更多的功能和灵活性, Nginx 中 access_log 指令与 error_log 指令都支持 syslog 方式输出日志。
syslog 协议与日志格式图
在 Nginx 官方文档 Logging to syslog 中有详细的说明,如下所示。
# 指定日志服务器地址和端口,缺省使用 UDP 协议 以及 514
server=address
# 设置日志来自于什么基础设施,如 RFC 3164中所定义,默认为 LOCAL7
# kern, user, mail, daemon, auth, intern, lpr, news, uucp, clock, authpriv, ftp, ntp, audit, alert, cron, local0..local7. Default is local7
facility=local7
# 设置 access_log 的syslog消息的严重性,如RFC 3164中所定义,默认为 info
severity=info
# 设置日志的标签,默认为 nginx
tag=nginx
# 禁止在syslog消息头中添加“主机名”字段(
nohostname
这里作者在 OpenEuler 24.04 LTS 操作系统中启用 rsyslog 8.x 服务,并设置接收 syslog 协议的日志传入。
# 配置文件 /etc/rsyslog.conf
$ grep -vE "^#" /etc/rsyslog.conf | sed '/^$/d'
global(workDirectory="/var/lib/rsyslog")
module(load="builtin:omfile" Template="RSYSLOG_TraditionalFileFormat")
module(load="imuxsock"# provides support for local system logging (e.g. via logger command)
SysSock.Use="off") # Turn off message reception via local log socket;
# local messages are retrieved through imjournal now.
module(load="imjournal"# provides access to the systemd journal
StateFile="/run/log/imjournal.state") # File to store the position in the journal
module(load="imudp") # 关键点: 启用 UDP 方式接收日志
input(type="imudp" port="514") # 关键点: 指定监听端口为514
$imjournalRatelimitInterval 0
include(file="/etc/rsyslog.d/*.conf" mode="optional")
*.info;mail.none;authpriv.none;cron.none /var/log/messages
authpriv.* /var/log/secure
mail.* -/var/log/maillog
cron.* /var/log/cron
*.emerg :omusrmsg:*
uucp,news.crit /var/log/spooler
local7.* /var/log/boot.log
local6.* /var/log/syslog/nginx.log # 关键点: 指定日志文件路径
# 验证配置
$ rsyslogd -N1
# 重启 rsyslog 服务
systemctl restart rsyslog
# 查看监听端口状态
$ ss -uan | grep ':514'
UNCONN 0 0 0.0.0.0:514 0.0.0.0:*
UNCONN 0 0 [::]:514 [::]:*
在 Nginx 配置文件中,你可以这样使用 syslog 来记录日志:
# 使用 syslog 方式输出 access 日志到远程服务器。
access_log syslog:server=192.168.1.100:514,facility=local6,severity=info,tag=nginx main;
# 其它
access_log syslog:server=[2001:db8::1]:12345,facility=local6,severity=info,tag=nginx combined;
access_log syslog:server=unix:/var/log/nginx.sock,nohostname;
# 使用 syslog 方式输出 error 日志到远程服务器。
error_log syslog:server=192.168.1.1 debug;
重启 Nginx 服务,访问 nginx 的虚拟站点,查看日志是否传入到 214 主机中,如下所示。
# 213 主机 - Nginx
nginx -s reload
# 214 主机 - 查看日志
$ ls -alh /var/log/syslog/nginx.log
-rw------- 1 root root 5.6K Mar 12 19:19 /var/log/syslog/nginx.log
$ tail -f /var/log/syslog/nginx.log
# 格式: time host program/tag message
Mar 12 19:20:08 weiyigeek-top nginx: 10.20.172.106 - - [12/Mar/2026:19:20:08 +0800] "GET /welcome/css/stylesheet.css HTTP/2.0" 200 1392 "https://office.weiyigeek.top/""Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36 Edg/145.0.0.0""-"
....
传输access日志到rsyslog图
至此, 你已经学会了如何在 Nginx 中配置使用 syslog 协议传输日志到远程服务器,以及如何通过 rsyslog 服务接收并存储这些日志。
最后有需要新手朋友们,可加入到作者知识星球中,完整系统的学习 Nginx 高性能Web服务器从入门到生产时间,后续也将持续更新 OpenResty 系列文章,感谢大家支持。
820