TCP socket SYN 대기 열과 Accept 대기 열의 차이 원리 분석
우선"LISTENING"상태 에 있 는 TCP socket 에는 두 개의 독립 된 대기 열 이 있다 는 것 을 알 아야 합 니 다.
SYN 대기 열
SYN 대기 열 은 SYN 패 키 지 를 받 은 연결(커 널 코드 에 대응 하 는 구조 체:struct inet_request_sock을 저장 합 니 다.SYN+ACK 가방 에 답장 하고 ACK 가방 을 받 지 못 했 을 때 시간 이 초 과 될 때 까지 다시 전달 하 는 것 이 직책 이다.Linux 에서 재 전송 횟수 는 다음 과 같 습 니 다.
$ sysctl net.ipv4.tcp_synack_retries
net.ipv4.tcp_synack_retries = 5
문서 에서tcp_synack_retries에 대한 설명 은 다음 과 같다.
tcp_synack_retries-int 정형
수 동적 TCP 연결 에 대해 SYNACKs 를 재 전송 하 는 횟수 입 니 다.이 값 은 255 를 초과 할 수 없다.
기본 값 은 5 입 니 다.초기 RTO 가 1 초 라면 마지막 리 셋 은 31 초 입 니 다.
대응 하 는 마지막 시간 초 과 는 63 초 후 였 다.
SYN+ACK 를 보 낸 후 SYN 대기 열 은 클 라 이언 트 에서 보 내 는 ACK 가방(즉 세 번 악수 하 는 마지막 가방)을 기다 리 고 있 습 니 다.ACK 패 키 지 를 받 았 을 때 먼저 해당 하 는 SYN 대기 열 을 찾 은 다음 해당 하 는 SYN 대기 열 에서 관련 데이터 가 일치 하 는 지 확인 합 니 다.일치 하면 커 널 은 이 연결 과 관련 된 데 이 터 를 SYN 대기 열 에서 제거 하고 완전한 연결(커 널 코드 에 대응 하 는 구조 체:struct inet_sock을 만 들 고 이 연결 을 Accept 대기 열 에 추가 합 니 다.
수락 대기 열
Accept 대기 열 에 저 장 된 것 은 연결 이 되 어 있 습 니 다.즉,상위 프로그램 에서 가 져 갈 연결 을 기다 리 는 것 입 니 다.프로 세 스 가 accept()를 호출 하면 이 socket 은 대기 열 에서 꺼 내 상위 프로그램 에 전 달 됩 니 다.
이것 이 바로 Linux 가 SYN 가방 을 처리 하 는 간단 한 설명 이다.참고 로 socket 이 TCP 를 열 었 을 때DEFER_ACCEPT 와 TCPFASTOPEN 시 작업 방식 이 조금씩 다 를 것 이 므 로 본 고 는 소개 하지 않 겠 습 니 다.
대기 열 크기 제한
응용 프로그램 은 시스템 호출 listen(2)을 통 해 backlog 인 자 를 입력 하여 SYN 대기 열과 Accept 대기 열의 최대 크기 를 설정 합 니 다.예 를 들 어 SYN 대기 열과 Accept 대기 열의 최대 크기 를 1024 로 설정 합 니 다.
listen(sfd, 1024)
4.3 버 전의 커 널 에 서 는 SYN 대기 열의 크기 를 다른 방식 으로 계산 합 니 다.
SYN 대기 열의 최대 크기 는 이전에 net.ipv4.tcp 를 사 용 했 습 니 다.max_syn_backlog 로 설정 하지만 이 제 는 사용 하지 않 습 니 다.현재 net.core.somaxconn 으로 SYN 대기 열과 Accept 대기 열의 최대 크기 를 동시에 표시 합 니 다.서버 에서 16k 로 설정 합 니 다.
$ sysctl net.core.somaxconn
net.core.somaxconn = 16384
위의 이 정 보 를 알 게 되면 대기 열 설정 이 얼마나 적합 한 지 물 어 볼 수 있 습 니 다.대기 열 설정 이 얼마나 적합 합 니까?
정 답 은 상황 을 보 는 것 이다.대부분의 TCP 서비스 에 있어 서 이것 은 그다지 중요 하지 않다.예 를 들 어 Go 언어 1.11 버 전 전에는 대기 열 크기 를 설정 하 는 방법 을 제공 하지 않 았 다.
그럼 에 도 불구 하고 합 리 적 인 이유 가 있 습 니 다.대열 의 크기 를 늘 려 야 합 니 다.
Liux 에서 SYN 대기 열의 현재 상 태 를 보 려 면 ss 명령 을 사용 하여 SYN-RECV 상태의 socket 을 조회 할 수 있 습 니 다.예 를 들 어 다음 과 같은 실행 결 과 는 80 포트 를 나타 내 는 SYN 대기 열 에 현재 119 개의 요소 가 있 고 443 포트 는 78 이다.
$ ss -n state syn-recv sport = :80 | wc -l
119
$ ss -n state syn-recv sport = :443 | wc -l
78
프로그램 호출 accept()가 빠 르 지 않 으 면?또한 우리 의 SystemTap 스 크 립 트 를 통 해 이 데 이 터 를 관찰 할 수 있 습 니 다.resq.stp
프로그램 호출 accept()가 부족 하면 무슨 일이 일어 날 까요?
커 널 의 이런 표현 은 대부분의 서비스 에 있어 서 받 아들 일 수 있다.참고 로 net.ipv4.tcp 조정 을 통 해abort_on_overflow 라 는 전역 매개 변 수 는 이러한 표현 을 수정 하지만 이 매개 변 수 를 바 꾸 지 않 는 것 이 좋 습 니 다.
nstat 의 수 를 보고 Accept 대기 열 이 넘 치 는 상 태 를 관찰 할 수 있 습 니 다:
$ nstat -az TcpExtListenDrops
TcpExtListenDrops 49199 0.0
하지만 이 는 전반적인 계산 이다.관찰 해 보면 직관 적 이지 못 하 다.예 를 들 어 가끔 우 리 는 그것 이 증가 하고 있 는 것 을 관찰 하지만 모든 서비스 프로그램 이 정상 적 으로 보인다.이 때 우 리 는 ss 명령 을 사용 하여 단일 감청 포트 의 Accept 대기 열 크기 를 관찰 할 수 있 습 니 다.
$ ss -plnt sport = :6443|cat
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 1024 *:6443 *:*
Recv-Q 열 은 Accept 대기 열 에 있 는 socket 수 를 표시 합 니 다.Send-Q 는 대기 열의 최대 크기 를 표시 합 니 다.위의 예 에서 우 리 는 프로그램 accept()의 socket 이 없 는 것 을 발 견 했 지만,Listen Drops 계수 가 증가 하고 있 는 것 을 발견 했다.
이것 은 우리 의 프로그램 이 영구적 으로 처리 하지 않 는 것 이 아니 라 주기 적 으로 잠시 멈 춰 서 새로운 연결 을 처리 하지 않 기 때 문 입 니 다.시간 이 지나 면 프로그램 이 다시 정상 으로 돌 아 왔 습 니 다.이러한 상황 에서 ss 명령 으로 는 이러한 현상 을 관찰 하기 어렵 기 때문에 우 리 는 하나의SystemTap 스 크 립 트를 썼 다.이것 은 커 널 에 훅 을 넣 고 버 려 진 SYN 가방 을 인쇄 할 것 이다.
$ sudo stap -v acceptq.stp
time (us) acceptq qmax local addr remote_addr
1495634198449075 1025 1024 0.0.0.0:6443 10.0.1.92:28585
1495634198449253 1025 1024 0.0.0.0:6443 10.0.1.92:50500
1495634198450062 1025 1024 0.0.0.0:6443 10.0.1.92:65434
...
위의 조작 을 통 해 어떤 SYN 가방 이 Listen Drops 에 영향 을 받 았 는 지 관찰 할 수 있 습 니 다.그래서 우 리 는 어떤 프로그램 이 연결 을 잃 어 버 리 고 있 는 지 알 수 있다.이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
UDP 체크섬 이해의 책에서 공부하고 있었습니다만, UDP의 체크섬의 부분이 약간 어려웠으므로 자신 나름대로 정리해 아웃풋 합니다. 소스 포트 번호 대상 포트 번호 체크섬 체크섬 이외의 설명은 불필요하다고 생각하므로 생략합니다. 체크...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.