[Nginx/Go/OpenGemini] API请求体过大时,报:413 Request Entity Too Large

目录

1 问题描述

CASE/20231226 : Nginx Web Server

  • 此问题(通过方法1)已解决,但整体的解决思路,参考自网友,故著名为【转载】文章

  • 昨晚压测时,通过API请求10000个设备的若干信号(5个)状态时,Postman返回Nginx的如下错误

API 整个请求有 1.37MB

413 Request Entity Too Large

CASE/20250106: Go/OpenGemini(ts-sql) Http Server

如果是 go server ,则可能报此类错误日志:

// opengemini : tail -f 100 /usr/local/opengemini/gemini-log/logs/ts-sql-8086/sql.log
{"level":"error","time":"2025-01-06T11:58:16.998985255+08:00","msg":"serveWrite","hostname":"10.45.32.2:8086","ContentLength":32398789,"error":"write error:StatusRequestEntityTooLarge","db":"xxx_db","errno":"11116413","location":"httpd/handler.go:1214","repeated":1}

handler.go#serveWrite - Github/OpenGemini

2 问题分析

针对 Nginx Web Server

  • 通过字面意思,即可知悉:nginxclient_max_body_size指令的默认值为 1 MiB 导致的。
  • 这一指令可以被设置在httpserverlocation语境。在大多数情况下,该指令在嵌套块优先于祖先块相同的指令。
  • client_max_body_size
  • client_max_body_size 默认 1M,表示 客户端请求服务器最大允许大小,在“Content-Length”请求头中指定。
  • 如果请求的正文数据大于client_max_body_size,HTTP协议会报错 413 Request Entity Too Large。
  • 就是说如果请求的正文大于client_max_body_size,一定是失败的。如果需要上传大文件,一定要修改该值。
  • client_body_buffer_size
  • Nginx分配给请求数据的Buffer大小,如果请求的数据小于client_body_buffer_size直接将数据先在内存中存储。
  • 如果请求的值大于client_body_buffer_size小于client_max_body_size,就会将数据先存储到临时文件中,在哪个临时文件中呢?
  • client_body_temp 指定的路径中,默认该路径值是/tmp/.所以配置的client_body_temp地址,一定让执行的Nginx的用户组有读写权限。

否则,当传输的数据大于client_body_buffer_size,写进临时文件失败会报错。

  • 设置客户端请求正文的最大允许大小,在“Content-Length”请求标头字段中指定。

如果请求中的大小超过配置的值,则会将413(请求实体太大)错误返回给客户端。
请注意,浏览器无法正确显示此错误。将大小设置为0将禁用检查客户端请求正文大小。

针对 Go/OpenGemini(ts-sql) Http Server

https://github.com/openGemini/openGemini/blob/v1.2.0/lib/util/lifted/influx/httpd/handler.go#L1214

handler.go#serveWrite

3 解决方法

针对 Nginx Web Server

  • 方法1:如果仅仅是调试目标微服务时,可以尝试避开nginx,直接请求 k8s 的 目标 pod。(仅适用于调试目标微服务)

  • 方法2:压缩请求内容

  • 方法3:调整 nginx 的 参数

  • 打开nginx主配置文件nginx.conf,,找到http {}段,修改或者添加:client_max_body_size / client_body_buffer_size配置项

一般在/usr/local/nginx/conf/nginx.conf这个位置。

vim /usr/local/nginx/conf/nginx.conf

    client_max_body_size 20m;
    client_body_buffer_size 20m;

    //include       mime.types;
    //default_type  application/octet-stream;

  • 重启nginx
/usr/local/nginx/sbin/nginx -s reload

针对 Go/OpenGemini(ts-sql) Http Server

  • 更新 ts-sql 服务进程的配置,再重启之

解决写入失败,ts-sql报 error:StatusRequestEntityTooLarge 的问题(默认:23.8MB)
默认值 = 25E6 Bytes = 25*10^6 Bytes = 25000000 Bytes = 23.8 MB

# vim /usr/local/opengemini/gemini-deploy-prod/ts-sql-8086/conf/ts-sql.toml
[http]
# 60MB = 62914560 Bytes
max-body-size = 62914560

关联问题: HTTP请求报请求头过大 414:Request-URI Too Large异常

  • 参考文献

原因分析

  • 客户端的HTTP请求 URL 太长,超过了Web服务器的限制,导致服务器拒绝处理请求,返回414异常。

特别注意,与 413 Request Entity Too Large 不同,413 是指请求体太大414 是指请求 URL 太长。

  • 对于 Nginx Web 服务器:
  • 请求头过大,超过large_client_header_buffer所设定的值时,Nginx可能返回“request uri too large”(414)或“bad-request”(400)错误。
  • 不仅如此,请求行中的最长一行也必须在large_client_header_buffer的限定范围内。
  • 如果请求行外的某一行的长度超过了一个buffer(默认为128k),也会导致返回“bad-request”(400)错误。

方法1: GET 请求改为 POST 【推荐】

  • 如果你的web请求是get请求,可以考虑调整为post请求。
  • get请求:当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。
  • post请求:原则上没有长度限制。
  • opengeminiinfluxdb 数据库的 org.influxdb:influxdb-java 客户端库为例
  • 2.20版本,不支持将url请求内容放post请求体
  • 2.22版本及以上,支持将url请求内容放post请求体
<!-- maven : https://mvnrepository.com/artifact/org.influxdb/influxdb-java/2.22 -->
<dependency>
	<groupId>org.influxdb</groupId>
	<artifactId>influxdb-java</artifactId>
	<!-- 2.22 / 2.23 / 2.24 -->
	<version>2.22</version>
</dependency>

org.influxdb:influxdb-java:org.influxdb.dto.Query#Query(java.lang.String, java.lang.String, boolean)

   /**
   * @param command the query command
   * @param database the database to query
   * @param requiresPost true if the command requires a POST instead of GET to influxdb (若 requiresPost == true,则:使用 POST 请求替代 GET 请求)
   */
   public Query(final String command, final String database, final boolean requiresPost) {
    super();
    this.command = command;
    this.database = database;
    this.requiresPost = requiresPost;
  }

方法2:入参分批查询

  • 将get请求分批入参进行查询(不建议,这里不做方法的详细描述)

方法3:调整 Nginx Web 服务器的阈值配置

需要对Nginx的配置文件nginx.conf进行相应的调整。在http段中加入以下参数:

  1. client_header_buffer_size: 设定客户端请求头的缓冲区大小。为了应对较大的请求头,我们可以将其设置为512k。
client_header_buffer_size 512k;
  1. large_client_header_buffers: 设定用于存储大型请求头的缓冲区数量和大小。这里我们设定4个缓冲区,每个大小为512k。
large_client_header_buffers 4 512k;
  1. client_max_body_size: 限制客户端请求体的最大尺寸。这里我们将其设定为100MB,以适应较大的数据请求。
client_max_body_size 100m;

完成上述配置后,保存并重启Nginx服务器,以使新的配置生效。这样,Nginx就能更好地处理大型请求头和请求体,不再出现“414 Request-URI Too Large”错误。


  • 华为云 (HTTP应用型) ELB 的底层本质是 Nginx

默认配置项为:

# 请求头: 32KB
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;

# 请求体 : 10000MB
client_max_body_size 10000m;
client_body_buffer_size 128k;

X 参考文献

  • PHP配置: 修改php.ini文件中的upload_max_filesize / post_max_size参数来增加上传限制
  • 有些WordPres插件也可帮助您增加上传限制,例如"WP Maximum Upload File Size"或"Upload Max File Size"
  • OpenGemini
  • [lib] handler.go#serverWrite

https://github.com/openGemini/openGemini/blob/v1.2.0/lib/util/lifted/influx/httpd/handler.go#L1214

  • config.go : h.Config.MaxBodySize
  • [lib] error/message.go#HttpRequestEntityTooLarge
  • [lib] error/error.go#ModuleHTTP = 11
  • [lib] errno/code.go#InternalError = 6413
posted @   千千寰宇  阅读(477)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
历史上的今天:
2020-12-26 [数据库] Oracle之数据迁移至HIVE(待续)
点击右上角即可分享
微信分享提示