TCP 버퍼가 실제로 사용하는 메모리 양을 어떻게 알 수 있나요?

TCP 버퍼가 실제로 사용하는 메모리 양을 어떻게 알 수 있나요?

약 1,000개의 지속적이고 매우 낮은 대역폭의 TCP 연결을 갖춘 프런트 엔드 시스템이 있습니다. 메모리가 좀 제한되어 있어서 몇 백 MB는 어디로 가는지 알아보려고 합니다. TCP 버퍼가 원인 중 하나일 수 있지만 다음 문제를 해결할 수 없습니다.

  1. 기억 보고서는 어디에 있나요? buff/cache프로젝트의 일부 입니까 top, 아니면 RES프로세스 측정의 일부입니까?
  2. 프로세스별 수준에서 이를 줄이려는 경우 감소가 원하는 효과를 갖도록 하려면 어떻게 해야 합니까?
  3. 최소한의 트래픽으로도 버퍼가 일부 메모리를 계속 차지합니까, 아니면 버퍼 크기가 동적으로 증가하고 버퍼 크기가 단순히 허용되는 최대 크기입니까?

가능한 대답 중 하나는 "커널이 이를 수행하도록 신뢰하는 것"이라는 것을 알고 있지만 TCP 버퍼를 메모리 압박의 원인으로 배제하고 싶습니다.

설문조사: 질문 1

이 페이지"'버퍼' 메모리는 Linux에서 네트워크 및 디스크 연결을 버퍼링하는 데 사용하는 메모리입니다. 이는 RESmesometric 의 일부가 아님을 의미합니다 top. "

실제 메모리 사용량을 찾으려면 /proc/net/sockstat가장 유망한 것은 다음과 같습니다.

sockets: used 3640
TCP: inuse 48 orphan 49 tw 63 alloc 2620 mem 248
UDP: inuse 6 mem 10
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

이것내가 찾을 수 있는 가장 좋은 설명이지만 mem거기에서는 해결되지 않았습니다. 해결됨여기, 그러나 248*4k ~= 1MB 또는 시스템 전체 최대값의 약 1/1000입니다. 이는 수백 개의 지속적인 연결과 일정한 0.2-.3Mbit/sec 네트워크 트래픽 번호를 가진 서버의 경우 터무니없이 낮은 것 같습니다.

물론 시스템 메모리 제한 자체는 다음과 같습니다.

$ grep . /proc/sys/net/ipv4/tcp*mem
/proc/sys/net/ipv4/tcp_mem:140631   187510  281262
/proc/sys/net/ipv4/tcp_rmem:4096    87380   6291456
/proc/sys/net/ipv4/tcp_wmem:4096    16384   4194304

tcp_mem세 번째 매개변수는 TCP 버퍼 전용의 시스템 전체 최대 4k 페이지 수입니다. 버퍼 크기의 합이 이 값을 초과하면 커널이 패킷 삭제를 시작합니다. 특별하지 않은 작업 부하의 경우 이 값을 조정할 필요가 없습니다.

다음은 /proc/meminfo신비 BuffersCached아이템과 함께 입니다. 여러 소스를 살펴봤지만 TCP 버퍼를 설명한다고 주장하는 소스를 찾을 수 없습니다.

...
MemAvailable:    8298852 kB
Buffers:          192440 kB
Cached:          2094680 kB
SwapCached:        34560 kB
...

설문조사: 질문 2-3

프로세스 수준에서 TCP 버퍼 크기를 확인하기 위해 많은 옵션이 있지만 그 중 어느 것도 현재 대기열 크기나 최대값이 아닌 실제 할당된 메모리를 제공하지 않는 것 같습니다.

가지다 ss -m --info:

State       Recv-Q Send-Q
ESTAB       0      0
... <snip> ....
skmem:(r0,rb1062000,t0,tb2626560,f0,w0,o0,bl0)  ...<snip> rcv_space:43690

그래서 우리는

  • Recv-QSend-Q현재 버퍼 사용량
  • r그리고 t, 설명은이 훌륭한 기사Recv-Q하지만, 와 가 어떻게 다른지 명확하지 않습니다 .Send-Q
  • 라는 것이 rb의심스럽게 최대 버퍼 크기처럼 보이지만 문서를 찾을 수 없습니다.
  • rcv_space, 어느이 페이지선언은 호출해야 하는 실제 버퍼 크기가 아닙니다.getsockopt

이 답변제안되었지만 lsofsize/off는 다음과 동일한 버퍼 사용량을 보고하는 것 같습니다 ss.

COMMAND     PID   TID                USER   FD      TYPE             DEVICE SIZE/OFF       NODE NAME
sslocal    4032                   michael   82u     IPv4            1733921      0t0        TCP localhost:socks->localhost:59594 (ESTABLISHED)

그런 다음이 답변lsof가 실제 버퍼 크기를 반환할 수 없음을 나타냅니다. 트릭을 수행하는 커널 모듈을 제공하지만그냥 작동하는 것 같습니다버퍼 크기가 전달됩니다 setsockopt. 고정 소켓이 아닌 경우 SO_SNDBUF 및 SO_RCVBUF는 포함되지 않습니다.

답변1

/proc/net/sockstat, 특히 mem필드를 살펴볼 곳입니다. 이 값은 커널 페이지에 보고되며 /proc/sys/net/ipv4/tcp_mem.

개별 소켓 수준에서 메모리는 사용자 공간 코드가 이를 읽을 때까지만 커널 공간에 할당되며, 이 시점에서 커널 메모리는 해제됩니다(참조:여기). sk_buff->truesize버퍼링된 데이터의 양과 소켓 구조 자체의 합계입니다(참조:여기, 메모리 정렬을 수정하기 위한 패치에 대해 논의합니다.여기)

내가 의심하는 필드는 mem단순히 모든 소켓을 합산 /proc/net/sockstat하여 sk_buff->truesize계산 되지만 커널 소스 코드에 익숙하지 않아 어디서 찾아야 할지 알 수 없습니다.

확인을 통해,이 기능 요청넷데이터 모니터링 시스템의 콘텐츠에는 많은 좋은 토론과 관련 링크가 포함되어 있으며 이러한 해석을 뒷받침합니다 /proc/net/sockstat.

이 게시물"소켓 메모리 부족" 오류에는 다양한 메모리 문제에 대한 보다 일반적인 논의가 포함되어 있습니다.

답변2

이는 매우 복잡한 질문이며 답을 찾으려면 커널 소스 코드를 파헤쳐야 할 수도 있습니다.

버퍼가 프로세스의 RES 통계에 포함되지 않은 것 같습니다. 바라보다이것기사(아직 읽지 않은 경우) 저자에 따르면:

장치 드라이버는 들어오는 패킷에 대해 DMA를 수행하기 위해 장치에 메모리 영역을 할당합니다.

"조정: 소켓 수신 큐 메모리" 섹션에는 최대 버퍼 크기가 나와 net.core.wmem_max있습니다 . net.core.rmem_max다시 말하지만 실제로 얼마나 많은 메모리가 사용되는지 확인하는 방법은 확실하지 않습니다.

분명히 네트워크 스택 내에는 문서화 수준이 낮고 복잡성이 높다는 문제가 있습니다. 여기있어

또한 버퍼링이 처리되는 방법에 대해 더 많이 읽을수록 바닐라 커널은 버퍼로 할당된 메모리 양 외에는 다른 것을 보는 것을 지원하지 않는 것 같습니다.

이것커널의 DMA에 대한 일부 문서도 여러분에게 유용할 수 있거나 적어도 여기서 어디로 가야 할지에 대한 아이디어를 제공할 수 있지만 현재로서는 제공된 커널 모듈이 여러분이 얻을 수 있는 가장 가까운 모듈이라고 생각합니다.

답변3

앞서 언급했듯이 mem 필드는 귀하의 질문과 관련된 필드입니다.

# cat /proc/net/sockstat
sockets: used 2512
TCP: inuse 2301 orphan 48 tw 3187 alloc 2304 mem 981
UDP: inuse 12 mem 2
UDPLITE: inuse 0
RAW: inuse 2
FRAG: inuse 0 memory 0

# echo $(( 981 * 4096  / 2**20 ))MB
3MB

관련 정보