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

t_u*_*a66 5 nginx nginx-config

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. 
Run Code Online (Sandbox Code Playgroud)

我知道缓冲区的大小是多少,但我不知道缓冲区的数目是多少。

处理如何根据缓冲区数量而变化?

小智 14

所以我大部分时间都在与一些 HTTP 标头长度作斗争,不得不弄清楚这一点。

TL;DR 缓冲区大小是您的缓冲区有多大,缓冲区编号是您拥有的缓冲区数量。因此,您的总容量为 num_buffs*buff_size + 1kb 常规标头缓冲区 = 总容量,需要注意的是,如果缓冲区中有足够的空间,标头只会进入缓冲区,或者换句话说,标头不会在缓冲区之间拆分.

对于源代码,我一直在通过使用不同大小的标头发出大量 curl 请求来弄清楚过去几个小时缓冲是如何工作的。

详细的解释。在 Nginx 中,有使用该client_header_buffer_size指令配置的默认头缓冲区。当请求头中的请求首先读入此缓冲区时,large_client_header_buffers只要请求头的总大小不超过为 配置的值client_header_buffer_size(默认为 1kb),就不会被占用。

然而,一旦我们突破了这个限制,事情就会变得有趣。作为Nginx的读取头入缓冲它将继续它们读入client_header_buffer,直到头到达比留在缓冲器中的空间,在该点处较大 large_client_header_buffers变得活跃,则整个报头将被读入第一large_client_buffer。然后Nginx的要继续读取头入client_header_buffer,直到它击中另一头,可以不适合留在空间client_header_buffer,此时它会检查它是否可以把请求头中的第一个large_client_buffer。如果不能,它将检查它是否可以将标头放在第二个中,large_client_buffer这个过程将在每个缓冲区上发生,直到满足两个条件之一:

  1. 所有标头都被成功处理并读入缓冲区

或者

  1. 任何缓冲区中都没有足够的空间来读取剩余的标头,因为没有更多的缓冲区具有足够的空白空间,或者因为请求标头大小超过了为缓冲区配置的大小。

当条件 2 发生时,Nginx 将响应一个错误,指示请求太大。

让我们通过一些例子来具体说明这一点。

对于我们的示例,我们将假设我们已将client_header_buffer称为 CHB 的 配置为 10kb 的大小,并且我们已配置两个large_client_header_buffers各为 20kb 的大小,分别称为 LCHB1 和 LCHB2。

场景 1 香草:

curl https://example.com -H 'h1: 3kb-long' -H 'h2: 2kb-long'

h2 | |

H1 | |

CHB | LCHB1 | LCHB2

在这种情况下,我们的头总共只有 5kb,因此很容易放入主缓冲区,我们可以在主缓冲区中支持多个头,只要它们的大小都不超过 5kb,无论是单独的还是集体的。

场景 2 比 CHB 缓冲区大的标头:

curl https://example.com -H 'h1: 14kb-long'

空 | H1 |

CHB | LCHB1 | LCHB2

在这种情况下,标头被直接读入大缓冲区,因为由于单个标头超出了为主缓冲区配置的大小,主缓冲区中没有空间容纳它。

场景 3 使用的所有缓冲区:

curl https://example.com -H 'h1: 19kb', -H 'h2: 19kb' -H 'h3: 9kb'

h3 | H1 | 小时2

乙肝| LCHB1 | LCHB2

在这种情况下,我们收到一个无法进入主缓冲区但刚好适合其中一个大缓冲区的标头,因此第一个标头进入那里。然后下一个头进入,也不能进入主缓冲区,但在第二个大缓冲区中有一个插槽,所以它进入那里。然后最终的标头可以适合主缓冲区的范围

场景 3 标题过多:

curl https://example.com -H 'h1: 19kb', -H 'h2: 19kb' -H 'h3: 9kb' -H 'h4: 2kb'

h4 | h3 | H1 | 小时2

错误 | CHB | LCHB1 | LCHB2

在这种情况下,场景开始上演类似于场景 3;然而,当我们引入一个额外的 2kb 标头时,我们遇到了一个问题。因此,在每个大缓冲区中使用 20kb 中的 19kb 和主缓冲区中剩余 1kb 的情况下,我们还有 3kb 的缓冲区空间,所以我们应该能够处理最后的 2kb 标头,对吗?错了,我的朋友。问题是当 2kb 头到达时 Nginx 在主缓冲区中查看并看到那里只剩下 1kb 的空间所以头不能去那里,然后它检查第一个大缓冲区,但仍然只有 1kb 的空间所以它不能去那里,最后它检查最终的大缓冲区才发现它仍然只有 1kb 的空间。此时 Nginx 返回一个错误,表明它收到了一个错误的请求,因为它无法将头读入。

因此,总而言之,缓冲区大小是您拥有的缓冲区有多大,但缓冲区的数量是该数字的乘数,即您必须保存请求标头的不同缓冲区的数量。


ast*_*civ 5

@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>
Run Code Online (Sandbox Code Playgroud)

nginx 将为前 4 个标头分配大缓冲区(因为它们不适合主 1k 缓冲区,也无法组合在一起以适合大型 4k 缓冲区),然后尝试将最后一个标头放入最后一个大缓冲区(已经满了),然后失败。但如果100b header先出现则不会有问题 - 它将被读入主(1k)缓冲区。