Nginx“large_client_header_buffers”指令最大大小的含义

xpcnnkqh  于 2022-12-03  发布在  Nginx
关注(0)|答案(2)|浏览(1190)

Nginx文档

Syntax: large_client_header_buffers number size;
Default: large_client_header_buffers 4 8k;
Context: http, server

Sets the maximum number and size of buffers used for reading large client request header.

我知道缓冲区的大小,但不知道缓冲区的数量。
处理过程如何根据缓冲区的数量而变化?

eiee3dmh

eiee3dmh1#

所以我一直在与一些HTTP头长度斗争的大部分晚上,并已弄清楚这一点。
TL;DR缓冲区大小是指缓冲区的大小,缓冲区数量是指缓冲区的数量。因此,总容量为num_buffs*buff_size +1 kb常规头缓冲区=总容量,注意,只有当缓冲区中有足够的空间时,头才会进入缓冲区,换句话说,头不会在缓冲区中分割。
对于源代码,我在过去的几个小时里一直在研究缓冲是如何工作的,方法是使用不同大小的头部发出大量curl请求。
详细说明。Nginx中有一个默认的头缓冲区,它是用client_header_buffer_size指令配置的。当一个请求进入时,头首先被读入这个缓冲区,只要请求头的总大小不超过client_header_buffer_size配置的值,默认为1 kb,large_client_header_buffers就不会被占用。
然而一旦我们突破了这个限制,事情就变得有趣了。当Nginx将头读入缓冲区时,它会继续将它们读入client_header_buffer,直到到达的头大于缓冲区中剩余的空间,此时X1 M4 N1 X变为有效,然后整个报头将被读入第一X1 M5 N1 X。然后Nginx会继续阅读头文件到client_header_buffer中,直到它遇到另一个头文件,这个头文件无法放入client_header_buffer中剩余的空间,此时它会检查是否可以将请求头文件放入第一个large_client_buffer中。然后,它将检查它是否可以将报头放置在第二个X1 M9 N1 X中。该过程将在每个缓冲器上发生,直到满足以下两个条件之一:
1.成功处理所有标头并将其读入缓冲区

1.任何缓冲区都没有足够的空间来读取剩余的标头,这可能是因为没有更多的缓冲区具有足够的可用空间,也可能是因为请求标头大小超过了为缓冲区配置的大小。
当条件编号2发生时,Nginx将以指示请求太大的错误来响应。
让我们通过一些例子来具体说明这一点。
在我们的示例中,我们假设已将client_header_buffer(称为CHB)配置为10 kb的大小,并已配置两个large_client_header_buffers(每个大小为20 kb,分别称为LCHB 1和LCHB 2)。
场景1香草:
curl 度https://example.com-H 'h1:3 kb长' -H 'h2:2kb长'
氢气||
第一层||
慢性乙型肝炎|LCHB 1基因|LCHB 2蛋白
在这种情况下,我们的头总共只有5 kb,因此很容易放入主缓冲区,并且我们可以在主缓冲区中支持多个头,只要它们的大小没有超过5 kb,无论是单独的还是共同的。
场景2大于CHB缓冲区的标头:
curl 度https://example.com-H 'h1:14 kb长度'
空的|第一层|
慢性乙型肝炎|LCHB 1基因|LCHB 2蛋白
在这种情况下,报头被直接读取到大缓冲器中,因为由于单个报头超过了为主缓冲器配置的大小,在主缓冲器中没有用于报头的空间。
方案3使用的所有缓冲液:
curl 度https://example.com-H 'h1:19kb ',-H 'h2:19kb“-H”h3:9kb'
h3值|第一层|氢气
慢性乙型肝炎|LCHB 1基因|LCHB 2蛋白
在这种情况下,我们接收到一个报头,它不能进入主缓冲区,但刚好适合其中一个大缓冲区,所以第一个报头进入那里。然后下一个报头进入,也不能进入主缓冲区,但在第二个大缓冲区中有一个槽,所以它进入那里。然后最后一个报头可以适合主缓冲区的限制
场景3标题太多:
curl 度https://example.com-H 'h1:19kb ',-H 'h2:19kb“-H”h3:9kb ′-H ′ h4:2kb'
四氢|h3值|第一层|氢气
错误|慢性乙型肝炎|LCHB 1基因|LCHB 2蛋白
在这种情况下,场景开始类似于场景3;然而,当我们引入额外的2kb报头时,我们遇到了一个问题。因此,在每个大缓冲区中使用了20 kb中的19 kb,主缓冲区中剩余了1 kb,我们还剩3 kb的缓冲区空间,因此我们应该能够处理最终的2kb报头,对吗?错,我的朋友。问题是当2kb的报头到达时,Nginx查看主缓冲区,发现那里只剩下1 kb的空间,所以报头不能到达那里,然后它检查第一个大缓冲区,但仍然只有1 kb的空间,所以它不能去那里,最后它检查最后一个大缓冲区,但发现它仍然只有1 kb的空间。在这一点上Nginx返回一个错误,表明它收到了一个坏的请求,因为它没有地方读头。
因此,总的来说,缓冲区大小是指您拥有的缓冲区的大小,但缓冲区的数量是该数字的倍数,即您必须保存请求头的不同缓冲区的数量。

watbbzwu

watbbzwu2#

@hpoe的回答很好,但是我想添加一些与我现在看到的工作方式不同的地方。显然,当nginx看到一个头文件不适合当前缓冲区时,它会为它分配一个大的缓冲区,然后这个缓冲区就成为当前缓冲区。
在nginx代码中可以看到这里和那里-当分配了大缓冲区时,它被分配给r->header_in,然后用于读取下一个头。
这意味着请求解析的成功与否取决于标头到达的顺序。例如,如果配置中有large_client_header_buffers 4 4k,则获取:

<2.5k header>
<2.5k header>
<2.5k header>
<4k header>
<100b header>

nginx将为前4个头分配大的缓冲区(因为它们不适合主1 k缓冲器,并且也不能合并在一起以适合大的4k缓冲器),然后尝试将最后的报头适合最后的大缓冲器(它已经满了),并且失败。但是如果100b header先来,那么就不会有问题-它会被读入主(1 k)缓冲区。

相关问题