약 1,000개의 지속적이고 매우 낮은 대역폭의 TCP 연결을 갖춘 프런트 엔드 시스템이 있습니다. 메모리가 좀 제한되어 있어서 몇 백 MB는 어디로 가는지 알아보려고 합니다. TCP 버퍼가 원인 중 하나일 수 있지만 다음 문제를 해결할 수 없습니다.
- 기억 보고서는 어디에 있나요?
buff/cache
프로젝트의 일부 입니까top
, 아니면RES
프로세스 측정의 일부입니까? - 프로세스별 수준에서 이를 줄이려는 경우 감소가 원하는 효과를 갖도록 하려면 어떻게 해야 합니까?
- 최소한의 트래픽으로도 버퍼가 일부 메모리를 계속 차지합니까, 아니면 버퍼 크기가 동적으로 증가하고 버퍼 크기가 단순히 허용되는 최대 크기입니까?
가능한 대답 중 하나는 "커널이 이를 수행하도록 신뢰하는 것"이라는 것을 알고 있지만 TCP 버퍼를 메모리 압박의 원인으로 배제하고 싶습니다.
설문조사: 질문 1
이 페이지"'버퍼' 메모리는 Linux에서 네트워크 및 디스크 연결을 버퍼링하는 데 사용하는 메모리입니다. 이는 RES
mesometric 의 일부가 아님을 의미합니다 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
신비 Buffers
와 Cached
아이템과 함께 입니다. 여러 소스를 살펴봤지만 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-Q
및Send-Q
현재 버퍼 사용량r
그리고t
, 설명은이 훌륭한 기사Recv-Q
하지만, 와 가 어떻게 다른지 명확하지 않습니다 .Send-Q
- 라는 것이
rb
의심스럽게 최대 버퍼 크기처럼 보이지만 문서를 찾을 수 없습니다. rcv_space
, 어느이 페이지선언은 호출해야 하는 실제 버퍼 크기가 아닙니다.getsockopt
이 답변제안되었지만 lsof
size/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