目录

2020

问题

最近在重构一个服务 , 为了在不影响目前正在运行的服务情况下 , 我用了 nginx 的 mirror 模块来观察和测试重构的服务 . 但是在比对新服务和老服务之间的 access_log 时 , 发现 mirror 的 access_log 丢失了一部分 . 在 google 后发现目前没人遇到和我同样的问题 ,所以这个问题特此记录下 .

mirror 模块如何配置 access_log

在解决这个问题之前我们先看看如何在 mirror 模块中配置 access_log 的 .

在 mirror 下是不能直接配置 access_log 的 , 一开始我还不知道 , nginx 的配置检测也通过了 , 但是就是不记录日志 . 错误的配置方式如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
				location /max {
            access_log  logs/max.log;
            mirror /mirror;
            default_type text/html;
            return 200;
        }
        location /mirror {
            access_log  logs/mirror.log;
            default_type text/html;
            return 200;
        }

我想实现的效果是在访问 /max 时会同时在 max.log 和 mirror.log 产生两条记录 . 可惜这种直观的方式不行 .

但是我们可以使用在 mirror 中使用反向代理 , 在代理的配置块中配置 access_log , 这种配置方式如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
server {
      listen       80;
      location /max {
          access_log  logs/max.log;
          mirror /mirror;
          default_type text/html;
          return 200;
      }
      location /mirror {
          proxy_pass http://127.0.0.1:10901$request_uri;
      }
}
server {
      listen 127.0.0.1:10901;
      location /mirror {
        default_type text/html;
        access_log  logs/mirror.log;
        return 200;
      }
}

排查

在对比两份 access_log 的过程中 , 我发现 mirror 丢失的都是 post 请求 , 并且这些请求的 request body 都比较大 , 大到一个请求记录一屏都放不下 . 所以怀疑是不是 client_max_body_size 配置的问题 . 看了配置文件后发现 nginx 源请求的 client_max_body_size 的值是 100m , mirror 没有配置该项 , 默认值是 1m . 感觉大概率是由于 mirror 的 max_body 太小导致的 . 但是一般来说 request body 的大小超过 client_max_body_size 肯定会返回 413 的状态码 , 而不是直接就丢失 access_log 的记录 , 所以我尝试在本地环境能不能复现 .

复现

本地 nginx 的配置文件如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
server {
      listen       80;
      location /max {
          access_log  logs/max.log;
          mirror /mirror;
          client_max_body_size 2k;
          default_type text/html;
          return 200;
      }
      location /mirror {
          proxy_pass http://127.0.0.1:10901$request_uri;
      }
}
server {
      listen 127.0.0.1:10901;
      location /mirror {
        default_type text/html;
        client_max_body_size 1k;
        access_log  logs/mirror.log;
        return 200;
      }
}

发送 body 很小的 request