Nginx buffer 配置问题记录

status
Published
type
Post
slug
nginx-buffer-config
date
Sep 20, 2022
tags
Nginx
Config
summary
最近在项目中遇到了一个问题:获取菜单树形结构数据的接口在初始时正常,过一段时间后就会出错。经过排查发现,这个问题和 Nginx 的 buffer 配置有关。Nginx 的 buffer 机制默认启用,它会将后端响应缓存在内存或磁盘上,然后再慢慢推送给客户端。但是如果后端响应较慢或数据量较大,同时缓冲区设置不足以容纳完整的响应数据,就会导致数据被截断。解决方法是调整 Nginx 的 buffer 配置,增加缓冲区的大小和数量,以及临时文件的写入大小和大小限制。此外,还可以调整超时设置。关闭 buffer 虽然可以解决问题,但不推荐,因为会影响到 Nginx 到后端的连接复用。
这几天在项目中遇到了一个问题:有一获取菜单的树形结构数据信息的接口,初始时正常,过一会儿后就会出错,清理缓存后又恢复正常
报错日志如下:
org.apache.http.TruncatedChunkException: Truncated chunk
即服务器返回的响应数据中的某个chunk(数据块)被截断或不完整,导致无法正确解析响应。
在正常的HTTP响应中,响应数据被分割成多个chunk,每个chunk都包含一个长度字段和对应长度的数据。当客户端接收到一个chunk时,它会解析长度字段,然后读取相应长度的数据。如果某个chunk的长度字段与实际数据长度不匹配,就会抛出Truncated chunk异常。
经过检查排除,最后发现和 Nginx buffer 配置相关。

请求过程

如下图所示为接口请求简化示意:
+------------------------+ | 客户端 | +-----------+------------+ | 请求/响应 | +-----------v------------+ | Nginx | +-----------+------------+ | 请求/响应 | +-----------v------------+ | 后端 | +------------------------+
过程中, Nginx 会利用其 buffer 机制来处理请求和响应,从而避免因客户端到Nginx与Nginx到后端服务的两个连接速度不一致而导致的不良影响。

Nginx buffer 机制

默认情况下,Nginx 会启用 buffer ,后端响应到达时,Nginx会将其缓存在内存或磁盘上,在接收到完整响应后再慢慢将其推给客户端。
在这次遇到的问题中,便是由此机制导致的:在后端服务响应较慢或数据量较大,同时缓冲区相关设置不足以容纳完整的响应数据,导致数据被截断。当后续请求再次访问接口时,由于缓存尚未过期,Nginx直接从缓存中返回数据,因此再次出现截断的数据块异常。

解决方法

  • 将Nginx配置中的 proxy_buffering 设置为 off
    • 即关闭 buffer,Nginx会按照响应内容的多少立即发送给客户端,可以解决此问题,但不推荐,因为会影响到Nginx到后端的连接复用。
  • 调整缓冲区大小和数量
    • 调整Nginx缓存内容至内存或磁盘相关的参数。
    • proxy_buffer_size:增加代理缓冲区的大小,以确保能够容纳较大的响应数据块。
    • proxy_buffers:增加代理缓冲区的数量,以提供更多的缓冲空间。
    • proxy_buffer_size 8k; proxy_buffers 4 8k;
  • 调整临时文件大小
    • proxy_temp_file_write_size:增加临时文件的写入大小,以确保大型响应数据可以正确写入临时文件。
    • proxy_max_temp_file_size:增加临时文件的大小限制,以避免将大型响应数据写入磁盘。
    • proxy_temp_file_write_size 8k; proxy_max_temp_file_size 10m;
此外,还可以调整超时设置:
proxy_connect_timeout:增加与后端服务器建立连接的超时时间。
proxy_read_timeout:增加从后端服务器读取响应数据的超时时间。
proxy_connect_timeout 30s; proxy_read_timeout 60s;
 
 

参考