I did multiple checks and it seems that the kernel allocates a quite large RCVBUF (receive buffer) of around 1-4MB.
Não por padrão, não. O tamanho é por soquete; Relacionamentos HTTP podem envolver vários soquetes. Não há, no meu caso, um máximo de sistema, a não ser que haja um número máximo (muito alto) de soquetes. De man 7 socket
:
SO_RCVBUF
Sets or gets the maximum socket receive buffer in bytes. The kernel doubles this value (to allow space for bookkeeping overhead) when it is set using setsockopt(2), and this doubled value is returned by getsockopt(2). The default value is set by the /proc/sys/net/core/rmem_default file, and the maximum allowed value is set by the /proc/sys/net/core/rmem_max file. The minimum (doubled) value for this option is 256.
Para mim, isso é:
> cat /proc/sys/net/core/rmem_default
212992
208 kB. No entanto, isso varia de acordo com o protocolo. De man 7 tcp
:
tcp_rmem (since Linux 2.4)
This is a vector of 3 integers: [min, default, max]. These parameters are used by TCP to regulate receive buffer sizes. TCP dynamically adjusts the size of the receive buffer from the defaults listed below, in the range of these values, depending on memory available in the system.
min: minimum size of the receive buffer used by each TCP socket. The default value is the system page size. (On Linux 2.4, the default value is 4K, lowered to PAGE_SIZE bytes in low-memory systems.) This value is used to ensure that in memory pressure mode, allocations below this size will still succeed. This is not used to bound the size of the receive buffer declared using SO_RCVBUF on a socket.
default: the default size of the receive buffer for a TCP socket. This value overwrites the initial default buffer size from the generic global net.core.rmem_default defined for all protocols. The default value is 87380 bytes. (On Linux 2.4, this will be lowered to 43689 in low-memory systems.) If larger receive buffer sizes are desired, this value should be increased (to affect all sockets). To employ large TCP windows, the net.ipv4.tcp_window_scaling must be enabled (default).
max: the maximum size of the receive buffer used by each TCP socket. This value does not override the global net.core.rmem_max. This is not used to limit the size of the receive buffer declared using SO_RCVBUF on a socket. The default value is calculated using the formula
max(87380, min(4MB, tcp_mem[1]*PAGE_SIZE/128))
(On Linux 2.4, the default is 87380*2 bytes, lowered to 87380 in low-memory systems).
Esse valor é informado em /proc/sys/net/ipv4/tcp_rmem
:
> cat /proc/sys/net/ipv4/tcp_rmem
4096 87380 6291456
Que pode ser confirmado com um pouco de C criando um único soquete TCP:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdio.h>
int main (int argc, const char *argv[]) {
int rcvbufsz;
socklen_t buflen = sizeof(rcvbufsz);
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
perror("socket() failed");
return 1;
}
if (getsockopt (
fd,
SOL_SOCKET,
SO_RCVBUF,
&rcvbufsz,
&buflen
) == -1) {
perror("getsockopt() failed");
return 1;
}
printf("SO_RCVBUF = %d\n", rcvbufsz);
return 0;
}
Relatórios compilados e executados SO_RCVBUF = 87380
, que corresponde à figura de /proc
. No entanto, o nginx está livre para ajustar isso para cima, não excedendo /proc/sys/net/core/rmem_max
, o que provavelmente é de 208 kB novamente.
O bit sobre como o TCP "ajusta dinamicamente o tamanho do buffer de recepção dos padrões [...] dependendo da memória disponível no sistema" (de man 7 tcp
) também vale a pena reafirmar.
Agora, a carne da sua pergunta ...
Since the proxy will buffer less data than the kernel, I don't see how the it helps to deal with slow clients. What can be the advantages of explicitly implementing/enabling a buffering feature in the proxy while the kernel does enough for us?
Tenha em mente que o buffer discutido acima não é um buffer de espaço de usuário. Geralmente, os aplicativos não fazem nada diretamente, embora seja a origem dos dados lidos. Portanto, os dados no próprio buffer do nginx não estão simultaneamente no buffer do kernel . Está sendo lido disso. A leitura esvazia o buffer. Então, isso em efeito aumenta a quantidade de dados armazenados em buffer por 8 * 8 = 64 kB.