HTTP, TCP 커넥션의 최적화를 위한 방법 - 병렬, 지속, 파이프라인 등
들어가며
- HTTP의 통신에 있어서 서버와 클라이언트가 request, respose를 수송신할 때, 트랜잭션을 어떻게 설정하고 유지할지가 주요 쟁점이다.
- 한 페이지가 요구하는 이미지와 데이터량이 계속하여 늘어나는 현 시대의 웹사이트에서 효율적인 커넥션은 매우 중요하다.
커넥션의 방식은 http 1.0과 1.1을 기준으로 아래와 같다.
- 병렬(parallel) 커넥션
- 지속(혹은 영속persistent) 커넥션
- 파이프라인(pipelined) 커넥션
그림 1 (출처 : https://developer.mozilla.org/ko/docs/Web/HTTP/Connection_management_in_HTTP_1.x)
1. 순차적인 트랜잭션의 처리 (short-lived connection)
- request와 response를 순차적으로 진행한다. 커넥션이 트랜잭션마다 새로 생성된다.
- 트랜잭션의 시작과 종료마다 커넥션의 시작과 종료를 반복하므로 성능상 문제가 발생할 수 있다. 특히 DNS, TCP 핸드셰이크 등 오버헤드가 반복적으로 발생한다. 핸드셰이크는 수백 바이트가 소모되고 여러 차례의 통신이 필요로 한 리소스가 큰 작업니다.
- 커넥션을 처음 시작했을 때, 인터넷 과부화를 막기 위하여 서버에서 최대 속도를 제한하는 경우가 있다. 이를 느린시작이라 한다. 커넥션을 반복적으로 처음부터 시작하면 느린시작으로 인한 속도 문제가 발생할 수 있다.
2. 병렬 커넥션
그림 2 (출처 : https://www.oreilly.com)
- 순차적인 트랜잭션 처리 문제의 해결책으로서, 커넥션을 한 번에 여러 번 생성하는 방식이다. 다수의 트랜잭션을 한 번에 맺으므로 빠르게 통신 가능하다.
- 다만, 과부하로 인한 성능 문제나 네트워크 대역폭의 한계로 인한 속도 문제가 발생하여 순차적인 방식보다 느릴 수도 있다.
- 각 트랜잭션마다 커넥션을 연결 및 종료한다는 점은 순차적인 트랜잭션 처리와 차이를 가지지 않는다.
3. 지속 커넥션 (Persistent connection)
- 순차적인 트랜잭션 처리가 가진 문제였던 커넥션 시작과 종료의 반복을 커넥션을 재활용하는 방식으로 개선하는 방식. 핸드쉐이크/지연로딩으로 인한 성능저하 문제를 해결한다.
- 오늘날 웹에서는 병렬 커넥션과 지속 커넥션을 함께 사용한다.
- http 1.0 기준으로 지속 커넥션을 사용하기 위해서 connection:Keep-Alive를 헤더에 포함시킨다. HTTP 1.1을 기준으로 default 값이 되었다.
- 사용하지 않는 커넥션이 계속 연결되어 있으면 성능 저하 문제가 발생할 수 있다. 클라이언트가 서버와 더이상 지속 커넥션을 필요로하지 않는 경우 마지막 요청에서 Connection:close로 커넥션 종료를 명시하거나 Connection:Keep-Alive 헤더를 더는 전달하지 않아야 한다.
- Connection 헤더는 hop-by-hop 특성을 가지므로, 단일 전송 경로(클라이언트-서버 또는 프록시-서버) 간에만 유효하며, 프록시가 이를 내부 서버로 전달하면 안 된다. 따라서 프록시 서버는 내부의 다른 서버로 요청을 전달하기 전에 Connection 헤더를 제거해야 한다. 이를 준수하지 않으면, 프록시 서버와 내부 서버 간 불필요한 지속 커넥션이 발생할 수 있다. HTTP/1.1에서는 이를 명확히 규정함으로써 문제가 줄어들었으며, HTTP/2부터는 멀티플렉싱과 커넥션 관리를 통해 이러한 문제를 근본적으로 해결했다.
hop-by-hop과 end-to-end 헤더? : https://devroach.tistory.com/110
4. 파이프라인 커넥션 (HTTP Pipelining)
- 지속 커넥션을 여러 트랜잭션으로 동시에 처리한다. 여러 개의 request와 여러 개의 response를 queue에 누적하여 처리한다.
- 파이프라인 커넥션은 요청 처리가 순차적으로 완료되는 것을 보장하지 않으며, 특히 POST와 같은 비멱등성 요청에서는 오류를 유발할 수 있다.
- HTTP/2 이후로는 거의 사용되지 않는다.
참고 : “http완벽가이드”, 데이빗 고울리 외 https://developer.mozilla.org/ko/docs/Web/HTTP/Connection_management_in_HTTP_1.x