NetWork[Persistent_connection]
지속 커넥션
웹 클라이언트는 보통 같은 사이트에 여러 개의 커넥션을 맺습니다.
서버에 HTTP 요청을 하기 시작한 애플리케이션은 웹 페이지 내의 이미지 등을 가져오기 위해 그 서버에 다시 요청을 하는데 이런 속성을 사이트 지역성 이라고 합니다.
이로 인해 HTTP/1.1 을 지원하는 기기는 TCP 커넥션을 유지하여 앞으로 있을 HTTP 요청에 재사용을 할 수 있습니다.
비 지속 커넥션은 각 처리가 끝날 때마다 커넥션을 끊었지만, 지속 커넥션은 클라이언트나 서버가 커넥션을 끊기 전까지는 트랜잭션 간에도 커넥션을 유지합니다.
이로 인해 많은 시간을 절약할 수 있고, TCP의 느린시작으로 인한 지연을 피함으로써 더 빠르게 데이터를 전송할 수 있습니다.
병렬 커넥션 단점
- 각 트랜잭션 마다 새로운 커넥션을 맺고 끊기 때문에 시간과 대역폭이 소모됩니다.
- 각각의 커넥션은 TCP의 새로운 시작 때문에 성능이 떨어집니다.
- 병렬 커넥션의 수에는 제한이 있습니다.
병렬 커넥션은 이러한 단점을 지녔지만, 지속 커넥션은 다음과 같은 장점이 있습니다.
지속 커넥션 장점
- 사전 작업과 지연을 줄여주고 튜닝된 커넥션을 유지합니다.
- 커넥션의 수를 줄여줍니다.
여기서 지속 커넥션을 잘못 관리할 경우 많은 커넥션이 쌓여 불필요한 소모를 발생 시키게 됩니다.
이러한 이유로 병렬 커넥션과 지속 커넥션을 함께 사용할 때에 효과적입니다.
HTTP/1.0+, Keep-Alive 커넥션
HTTP 1.0에서는 다소 Keep-Alive옵션이 실험적이었지만, Keep-Alive 지속 커넥션을 지원하기 위해 확장되어 나온 버전이 HTTP/1.0+ 입니다.
Keep-Alive는 커넥션을 끊지 않고, 계속적으로 유지하겠다는 옵션입니다.
클라이언트나 서버는 Keep-Alive 요청을 받았다고 해서 무조껀 따를 필요도 없으며, 언제든지 커넥션을 끊을수 있고, 처리되는 트랜잭션의 수를 제한할 수 있습니다.
Keep-Alive 동작
- 먼저 HTTP/1.0 Keep-Alive 커넥션을 구현한 클라이언트는 커넥션을 유지시키기 위해 요청에 Connection;Keep-Alive 헤더를 포함시킵니다.
- 이런 요청을 받은 서버는 그 다음 요청도 이 커넥션을 통해 받고자 하면은 응답 메시지에 같은 헤더를 포함시켜 응답합니다.
- 응답에 Connection:Keep-Alive 헤더가 존재 한다면 커넥션을 유지하겠다는 뜻이지만, 만약 헤더가 없으면 클라이언트는 서버가 Keep-Alive를 지원하지 않으며, 응답 메시지가 전송되고 나면 서버 커넥션을 끊을 것이라 추청합니다.
Keep-Alive 옵션
- timeout 파라미터
- 커넥션이 얼마간 유지될 것인지를 의미합니다.
- max 파라미터
- 커넥션이 몆개의 HTTP 트랜잭션을 처리할 때까지 유지될 것인지를 의미합니다.
참고로 Keep-Alive는 Connection:Keep-Alive 헤더가 있을때 만 사용이 가능합니다.
Keep-Alive 커넥션 제한과 규칙
Keep-Alive 커넥션에 대한 몆 가지 제한과 사용 방법에 대해 알아보겠습니다.
- Keep-Alive는 HTTP/1.0 에서 기본으로 사용되지 않습니다.
만약 커넥션을 계속 유지하려면 모든 메세지에 Keep-Alive 헤더를 포함해야 한다.
→ 클라이언트에서 서버로 넘어가고 나면, 서버에서 다시 다른 서버 ( 홉 바이 홉 ) 으로 전달 할 때 Connection헤더를 삭제하기 때문입니다.
- 만약 클라 응답 해더에 Connection : Keep-Alive 헤더가 없다면, 서버가 응답 후에 커넥션을 끊는다는 사실을 알 수 있습니다.
- 커넥션이 끊어지기 전에 엔티티 본문의 길이를 알 수 있어야 커넥션을 유지할 수 있습니다.
- 프록시와 게이트웨이는 Connection 헤더의 규칙을 철처히 지켜야 합니다.
Connection 헤더를 이해하지 못하는 프록시 서버와는 Keep-Alive를 사용하여 커넥션을 맺으면 안됩니다.
→ 구형 프록시 서버는 Connection헤더를 이해하지 못합니다.
HTTP/1.0을 따르는 기기로부터 받는 모든 Connection 헤더 필드는 무시해야 합니다.
→ 이 또한 구형 프록시에서 문제를 일으키기 때문입니다.
Keep-Alive와 구 프록시
앞에서 말했듯 Connection : Keep-Ailive가 헤더에 명시 되어있으면 클라이언트가 현재 연결하고 있는 TCP 커넥션을 끊지 않고 계속 유지한다는 뜻 입니다.
하지만 구 프록시에서는 이런 헤더를 알지 못하여, Connection : Keep-Ailive헤더가 명시된 요청이 오면 이를 삭제하고 다음 프록시나 서버에 전달을 해야하는데 이를 삭제하지 않은채 다음 서버나 프록시 서버에 전달을 하게 됩니다.
이렇게 되면 발생하는 문제에 대해 알아보겠습니다.
- 먼저 클라이언트는 Connection : Keep-Ailive헤더를 명시하여 프록시에게 요청 메세지를 전달합니다.
- 구 프록시는 요청 메세지를 받았지만 Connection : Keep-Ailive헤더를 이해하지 못하기에 그대로 다음 서버에 메세지를 전달합니다.
- 원래는 Connection : Keep-Ailive헤더를 지우고 전달해야 합니다 → ( 홉 바이 홉 )
- 프록시로부터 해당 요청을 받는 서버는, Connection : Keep-Ailive헤더가 명시 되어있기 때문에 TCP 커넥션을 유지할것이라 생각하고, Connection : Keep-Ailive헤더를 응답 메세지에 포함 시켜 프록시에게 응답 요청을 보낸 후, 커넥션을 유지합니다.
- 서버로부터 구 프록시는 응답메세지를 받았지만, Connection : Keep-Ailive헤더를 이해 하지 못하기에 다시 그대로 메세지를 클라이언트로 보낸 후, 새 요청을 모두 무시하면서 커넥션이 끊어지기를 기다립니다.
- 클라이언트는 Connection : Keep-Ailive헤더가 포함된 응답메세지를 받았기에 프록시가 커넥션 유지에 동의한다는 것으로 추청합니다. 이후, 다른 요청을 보내면 이 요청은 처리되지 않고 행에 걸립니다.
이렇게 되면 프록시는 클라이언트와 서버 둘다 커넥션을 끊기를 기다리지만, 클라이언트와 서버는 프록시와 커넥션을 계속해서 유지하고 있습니다.
브라우저는 자신이나 서버가 타임아웃이 나서 커넥션이 끊길때까지 계속 기다리게 되는 상황이 발생하게 됩니다.
이런 상황을 피하려면 프록시는 Connection헤더뿐만 아니라 Keep-Alive란 이름의 헤더도 절대로 전달하면 안됩니다.
Proxy-Coneeton
하지만 이런 문제점을 해결하기 위한 방법 또한 존재합니다.
기존의 Connection: Keep-Alive대신 Proxy-Connection: Keep-Alive헤더를 사용하면 됩니다.
Proxy-Connection: Keep-Alive헤더는 프록시가 이 헤더를 읽어들이고 다음 서버에 전달하여도 서버는 이 헤더를 무시하기 때문에, 이전에 언급됬던 문제를 해결할 수 있습니다.(구 프록시, 신버전 프록시 둘 다 해당)
하지만, 프록시 서버가 1대인 경우에는 문제가 없지만, 2대 이상의 프록시가 존재 한다면 다시 이전에 언급됬던 문제가 다시 발생합니다.
그래서 Proxy-Connection: Keep-Alive를 사용하려면 프록시 서버가 1대인 경우에만 사용하는 것이 좋습니다.
HTTP/1.1의 지속 커넥션
HTTP/1.0에서는 지속 커넥션(Keep-Alive)를 활성화 하려면 별도의 설정이 필요 했지만, HTTP/1.1의 버전으로 넘어오면서 지속 커넥션(Keep-Alive)가 기본으로 활성화 되어 있습니다.
참고로 HTTP/1.1 애플리케이션은 트랜잭션이 끝난 다음에 커넥션을 끊으려면 Connection: close 헤더를 명시해야 합니다. 해당 헤더가 없으면 응답 후에도 커넥션을 유지하는 것으로 간주합니다.
지속 커넥션의 제한, 규칙
- 클라이언트가 요청에 Connection: close 헤더가 포함해 요청을 보내면 클라는 해당 커넥션에 추가적인 요청을 보낼 수 없습니다.
- 추가적인 요청이 없다면, Connection: close 헤더를 포함시켜야 합니다.
- 커넥션에 있는 모든 메시지가 자신의 길이 정보를 정확히 갖고 있을 때만 커넥션을 지속시킬 수 있습니다.
- HTTP/1.1 프록시 서버는 클라이언트와 서버 각각에 대해 별도의 지속 커넥션을 맺고 관리해야 합니다.
- HTTP/1.1 프록시 서버는 클라이언트가 클라이언트의 지원 범위를 모르면 지속 커넥션을 맺으면 안된다. ( Connection 헤더 전달 문제 )
- HTTP/1.1 기기는 Connection 헤더의 값과는 상관없이 언제든지 커넥션을 끊을 수 있어야 한다.
- HTTP/1.1 애플리케이션은 중간에 끊어지는 커넥션에 복구 할 수 있어야 한다.
- 클라이언트는 커넥션이 도중에 끊어지면 요청을 다시 보낼 준비가 되어 있어야 한다.
- 하나의 사용자 클라이언트는 두 개의 지속 커넥션만을 유지해야 한다. ( 과부하 방지 )