TCP 킵얼라이브와 HTTP 킵얼라이브에 대해 어리석게 혼란스러워함
TCP keepalive는 TCP의 keepalive 타이머입니다. 평신도의 관점에서 보면 TCP에는 시간 초과 후 예약된 작업이 있으며 해당 작업은 피어가 살아 있는지 확인하기 위해 피어에 감지 메시지를 보내는 것입니다. (“2시간 안에 연락이 없으면 도망가세요.”라는 줄거리를 생각해 보세요.)
개념대로 상대가 살아 있는지 감지하여 공격을 방지하는 데 사용됩니다. 연결이 "중간" 상태에서 해제됩니다.
소위 반 개방이란 네트워크 연결의 양쪽 끝 중 하나가 연결 해제되었지만 다른 쪽 끝은 여전히 연결되어 있음을 의미합니다.
(그림 1) TCP keepalive 흐름도
연결의 양쪽 끝이 통신하는 동안 예약된 작업 A가 있습니다. 메시지가 전송될 때마다 타이밍이 재설정됩니다. . 과제 A. 예약된 작업 tcp_keepalive_time의 제한 시간 내에 새로운 메시지 전송이 없으면 예약된 작업 A가 트리거되어 피어에게 생존 감지 메시지를 보냅니다. 위 그림과 같이 응답 메시지의 다양한 상황에 따라 다양한 작업 분기가 있습니다.
예약된 작업 B는 주기적으로 실행됩니다. 구체적인 논리는 예약된 작업 A의 감지 메시지가 응답 메시지를 받지 못하면 예약된 작업 B가 실행되기 시작한다는 것입니다. 태스크 B의 내용도 프로브 메시지를 보내는 것이지만 차이점은 B가 tcp_keepalive_intvl의 시간 간격으로 tcp_keepalive_probes회 실행된다는 것입니다. B의 탐지 메시지도 응답 메시지를 수신한 후 예약된 작업 A를 재설정하여 연결 상태를 유지합니다.
시스템 파일에는 위에서 언급한 세 가지 매개변수가 존재하며, 구체적인 경로는 다음과 같습니다.
통신의 양쪽 끝에는 데이터 버퍼로서의 파일이 있고, 다른 쪽 끝은 이를 로컬 전류로 보냅니다. 포트 데이터는 이 파일에 버퍼링됩니다. 위에서 언급한 "연결 끊기"는 파일을 닫는 것을 의미하며, 현재 포트로 전송된 모든 데이터는 버퍼에 저장되지 않습니다. 즉, 데이터가 삭제됩니다.
이 버퍼 파일을 보려면 lsof -i :8080 명령을 전달하고 8080을 포트 번호로 변경하세요.
HTTP keepalive는 지속적인 연결을 의미하며 TCP 연결의 재사용을 강조합니다. (유사한 시나리오: 전화를 끊기 전에 항상 질문하고, 아무 일도 일어나지 않으면 끊고, 통화 시간을 연장하여 새로운 주제가 없는지 확인하세요.)
TCP 연결 기간을 생성부터 연장합니다. TCP 연결이 종료되면 더 많은 데이터를 전송할 수 있습니다.
(그림 2) HTTP keepalive 흐름도
통신 연결의 양쪽 끝이 통신하는 동안 HTTP 수준의 keepalive 예약 작업이 있습니다. 클라이언트가 요청을 시작하고 응답을 받으면 예약된 작업이 트리거됩니다. 예약된 작업은 타이밍을 시작하고 연결 유지 시간 거리에 도달한 후 연결이 닫힙니다. 해당 기간 동안 클라이언트가 요청을 다시 시작하고 응답을 받으면 예약된 작업이 재설정되고 처음부터 시간이 측정됩니다.
그림 2는 Python의 소켓 라이브러리를 예로 들어 HTTP "요청-응답" 프로세스 중 최하위 수준의 연결 해제 프로세스에서 HTTP 유지(또는 HTTP 영구 연결)가 어떻게 작동하는지 보여줍니다. 연결 시간.
Python의 요청 라이브러리를 사용하여 예를 들어보는 것은 어떨까요? 요청의 최하위 계층도 소켓 연결 관리입니다. 차이점은 요청이 HTTP 프로토콜을 지원하고 HTTP 정보의 다양한 부분을 구문 분석할 수 있다는 것입니다. 소켓은 파일 버퍼에서 바이너리 스트림만 읽습니다. 마찬가지로, 다양한 웹 프레임워크의 요청 및 응답 개체 내부는 여전히 소켓 연결 관리입니다. 소켓을 언급하는 것만으로도 많은 간섭 정보를 제거할 수 있습니다.
서버 측 HTTP 연결 유지 시간 초과 후 데이터 폐기에 대한 설명입니다.
이제 막 시작하는 학생들은 저처럼 혼란스러울 수 있습니다. 서버는 연결 유지 시간이 초과된 후 받은 데이터를 버릴 것인데, 앞으로 서버가 포트에서 데이터를 어떻게 받을 수 있을까요?
서버의 포크 모델을 언급해야 합니다. 서버의 메인 프로세스는 포트를 수신하고 데이터가 도착하면 처리를 위해 하위 프로세스로 전달되고, 메인 프로세스는 루프에서 포트를 계속 수신합니다.
구체적으로 데이터가 도착하면 메인 프로세스는 먼저 새로운 소켓 연결 핸들을 생성합니다(핵심은 소켓 파일 설명자를 생성하여 디스크에 드롭하고 포트 데이터는 그런 다음 하위 프로세스를 분기합니다. 기본 프로세스는 새 소켓 핸들을 닫고 하위 프로세스는 소켓 핸들 연결을 유지합니다(모든 프로세스에서 소켓 핸들이 닫히면 TCP는 4번 흔들기 시작합니다). , 하위 프로세스가 클라이언트와의 통신을 인수합니다.
(그림 3)의 예와 마찬가지로 기본 프로세스는 많은 하위 프로세스를 분기합니다. A와 B는 서로 다른 클라이언트의 요청에 연결됩니다. 소켓 파일 설명자 a는 b의 데이터에 영향을 미치지 않습니다. .읽고 쓰세요.
(그림 3) 포크 모델에서 소켓 핸들을 전송하는 과정
결론은 서버와 외부 세계 사이에 설정된 각 소켓 연결이 독립적인 파일 설명자와 독립 하위 프로세스는 클라이언트와 통신합니다. 서버 측 연결 해제는 전체 포트의 데이터 교환을 닫는 것이 아니라 특정 파일 설명자의 읽기 및 쓰기를 닫는 것을 의미하며 다른 소켓 연결 간의 통신에는 영향을 미치지 않습니다. 폐기한다는 것은 외부에서 이 소켓 파일 디스크립터로 전송된 데이터가 아직 남아 있으면 폐기된다는 것을 의미합니다. 왜냐하면 이 파일 디스크립터가 쓰기가 비활성화되어 당연히 데이터를 착륙시킬 수 없기 때문입니다.
TCP keepalive는 시스템이 질서정연하게 작동하도록 보장하여 시스템이 결국 반쯤 열린 소켓 연결을 복구할 수 있도록 보장하는 백업 메커니즘과 비슷합니다. 그렇지 않으면 더 이상 연결을 수행할 수 없습니다. 장기간 작동 후 더 많은 요청을 수신합니다(시스템의 최대 소켓 연결 수 제한).
HTTP keepalive는 애플리케이션 계층의 작업으로, TCP keepalive의 기본 카운트다운 값이 매우 길기 때문에 서버 애플리케이션이 독립적으로 소켓 해제를 결정할 수 있도록 합니다. 일반적으로 그렇게 오래 기다릴 필요는 없습니다. 직설적으로 말하면, TCP에는 타이머가 있고 HTTP도 자체 타이머를 설정할 수 있습니다. HTTP의 타이머가 먼저 초과되면 TCP가 4파파 프로세스에 들어가도록 할 권한도 있습니다.
특정 데이터 패킷이 전송된 후 두 개의 Keepalive 예약 작업이 동시에 존재하며 함께 카운트다운 상태에 들어갑니다. 하나는 시스템 커널 TCP 코드와 관련된 프로그램이고 다른 하나는 high-alive 상태입니다. 레벨 프로그래밍 언어(Python/Java/Go 등) 웹 프레임워크 코드 프로그램은 충돌 없이 함께 실행됩니다.
HTTP keepalive는 애플리케이션 계층에 있는 것입니다. 프로덕션 중에 외부 서비스를 제공하는 애플리케이션에는 Gunicorn의 keepalive 및 Nginx의 keepalive_timeout과 같은 keepalive 매개변수가 있습니다. 이 매개변수를 통해 좀 더 고급 수준에서 다음 데이터를 기다리는 시간을 제어할 수 있습니다.
또한 동일한 서버에 N개의 웹 서비스가 있는 경우 TCP keepalive 매개변수는 전역적으로 적용되며 조정하기 어렵습니다.
네트워크 구조가 client-nginx-web 서버와 유사한 경우 nginx와 웹 서버의 keepalive 매개변수 크기를 일치시키는 문제도 고려해야 합니다. Keepalive 매개변수 사용에 대한 Gunicorn의 제안은 다음과 같습니다. :
웹의 대기 시간이 nginx보다 훨씬 짧고 client-nginx의 연결이 여전히 존재한다고 가정하면 nginx-web의 연결이 끊어지고 웹에서 일부 데이터가 누락됩니다. 고객 여러분, 결과가 참을 수 없습니다. 따라서 너무 차이가 나지 않도록(너무 짧지도, 너무 길지도 않게) nginx의 대기 시간에 맞춰 조정하는 것이 가장 좋습니다.
너무 길지 않은 것에 대해 한 가지 더 말씀드리겠습니다.
오랫동안 기다리면 웹 서비스에 많은 연결이 누적되어 유지됩니다. 이렇듯 새로운 요청이 들어올 수 없으며, 유지되고 있는 연결의 활용률이 높지 않을 수 있습니다. (클라이언트 코드가 중단점이거나 클라이언트가 오래 전에 닫혔을 수 있습니다.) 그 결과 서버 netstat에 여러 연결이 표시되고 모든 새 요청이 일시 중단되거나 심지어 삭제됩니다.