HTTP 커넥션

IKNOW·2024년 1월 8일
0

TCP 커넥션

모든 HTTP 통신은 패킷 교환 네트워크 프로토콜들의 계층화된 집합인 TCP/IP를 통해 이루어진다. 모든 클라이언트 애플리케이션은 서버 애플리케이션으로 TCP/IP 커넥션을 맺을 수 있다. 일단 커넥션이 맺어지면 클라이언트와 서버 컴퓨터 간에 주고 받는 메시지들은 손실 혹은 손상되거나 순서가 뒤바뀌지 않고 안전하게 전달된다

URL을 입력받은 브라우저는 다음과 같은 단계를 수행한다.

http://www.joes-hardware.com:80/power-tools.html

  1. 브라우저가 www.joes-hardware.com이라는 호스트 명을 추출한다.
  2. 브라우저가 이 호스트 명에 대한 IP주소를 찾는다.
  3. 브라우저가 포트 번호 80을 찾는다.
  4. 브라우저가 202.43.78.3dml 80포트로 TCP커넥션을 생성한다.
  5. 브라우저가 서버로 HTTP GET 요청 메시지를 보낸다.
  6. 브라우저가 서버에서 온 HTTP응답 메시지를 읽는다
  7. 브라우저가 커넥션을 끊는다.

TCP

HTTP 커넥션은 일부 규칙을 제외하고는 TCP커넥션이라 볼 수 있다. TCP커넥션은 인터넷을 안정적으로 연결해주기 때문에, 신속하고 정확하게 데이터를 보내고자 한다면 TCP의 기본적인 내용을 알아야한다.

TCP 스트림은 세그먼트로 나뉘어 IP패킷을 통해 전송된다.

TCP는 IP패킷을 통해 데이터를 전송한다. HTTP는 IP, TCP, HTTP로 구성된 프로토콜 스택에서 최상위 계층이다.

HTTP가 메시지를 전송하고자 하는 경우, 연결되어 있는 TCP 커넥셩을 통해서 메시지 데이터의 내용을 순서대로 보낸다. TCP는 세그먼트 단위로 데이터 스트림을 잘게 나누고, 세그먼트를 IP 패킷에 담아서 인터넷을 통해 데이터를 전달한다.

각 TCP 세그먼트는 하나의 IP주소에서 다른 IP주소로 IP패킷에 담겨 전달된다. IP패킷은 IP패킷 헤더, TCP 세그먼트 헤더, TCP 데이터 조각을 포함하고있다.

IP 헤더는 발신지와 목적지의 IP주소, 크기 등등을 갖고, TCP세그먼트 헤더는 TCP 포트 번호, TCP 제어 플래그, 그리고 데이터 순서와 무결성을 검사하기 위한 숫자값을 갖는다.

TCP 커넥션 유지하기

TCP 커넥션은 네가지 값으로 식별한다.

<발신지 IP주소, 발신지 포스, 수신지 IP주소, 수신지 포트>

네 가지 값이 모두 같은 TCP커넥션은 존재하지 않는다. (일부가 같을 수는 있다.)

TCP소켓 프로그래밍

소켓 API를 사용하면, TCP 종단 데이터 구조를 생성하고, 원격 서버의 TCP종단에 그 종단 데이터 구조를 연결하여 데이터 스트림을 읽고 쓸수 있다. TCP API는, 기본적인 네트워크 프로토콜의 핸드셰이킹, 그리고 TCP데이터 스트림과 IP 패킷 간의 분할 및 재조립에 대한 모든 세부사항을 외부로부터 숨긴다.

최초에 웹 서버는 커넥션을 기다리고 클라이언트는 URL을 통해 UP주소와 포트번호를 통해 TCP커넥션을 생성한다. 커넥션이 맺어지면, 클라이언트는 HTTP 요청을 보내고 서버는 그것을 읽는다. 서버가 요청 메시지를 다 읽고 그 요청에 해당하는 동작을 수행하여 클라이언트에 응답을 보내고 커넥션을 닫는다. 클라이언트는 응답을 받은후 커넥션을 닫는다.

(커넥션을 맺는 자세한 방법은 3-way HandShaking)

HTTP Connection

순차적인 트랜잭션 처리에 의한 지연

커넥션 관리가 제대로 이루어지지 않으면 TCP 성능이 안좋아 질 수 있다.

각 트랜잭션이 새로운 커넥션을 필요로 한다면 커넥션을 발생하는 지연과 함께 느린 시작지연이 발생할 수 있다.

순차적인 처리로 인한 지연의 단점으로는 물리적인 지연 뿐만 아니라 큰 이미지를 내려받는 중에는 나머지 공간에 변화가 없기 때문에 심리적인 지연도 느껴지게 된다.

때문에 HTTP 커넥션의 성능을 향상시킬수 있는 여러 기술들이 있다.

병렬 커넥션

순차적인 트랜잭션 처리는 너무 느리기 때문에 클라이언트가 여러개의 커넥션을 맺음으로써 여러개 HTTP 트랜잭션을 병렬로 처리할 수 있게 한다.

병렬 커넥션은 페이지를 더 빠르게 내려받는다.

단일 커넥션의 대여폭 제한과 커넥션이 동작하지 않고 있는 시간을 활용하여 객체가 여러개 있는 웹페이지를 빠르게 내려 받을 수 있다.각 커넥션의 지연시간을 겹치게 하면 총 지연 시간을 줄일 수 있고, 인터넷 대역폭이 충분하다면 다른 객체를 내려받는데 남은 대여폭을 사용할 수 있다.

병렬 커넥션이 항상 더 빠르지는 않다

클라이언트의 네트워크 대역폭이 좁을 경우에는 대부분 시간을 데이터를 전송하는데만 쓰이고 커넥션 지연이 차지하는 부분이 적기 때문에 성능상 장점이 사라지게 되고, 다수의 커넥션은 메모리를 소모하고 성능 문제를 발생시킬 수 있다.

병렬 커넥션은 더 빠르게 느껴질 순 있다.

병렬 커넥션이 항상 더 빠르게 로드하지는 않지만, 화면에 여러개의 객체가 동시에 보이면서 내려받는 상황이 보인다면, 사용자는 더 빠르게 내려받고 있는 것처럼 느낄 수 있다. (처음에는 저해상도로 시작하여 점차 해당도가 높아지는 형태의 웹 사이트도 비슷한 방법이다.)

사용자는 페이지의 총 다운로드 시간이 더 걸리다 하더라도, 화면에서 여러 작업이 일어나는 것을 눈으로 확인할 수 있으면 그것을 더 빠르다고 느낀다.

지속 커넥션

클라이언트는 일반적으로 같은 사이트에 여러개의 커넥션을 맺는다. 지속커넥션은 처리가 완료된 후에도 TCP; 커넥션을 유지하여 앞으로 있을 HTTP 요청에 재사용 할 수 있다.

지속 커넥션을 재사용 하면, 커넥션을 맺기 위한 준비작업에 따르는 시간을 절약할 수 있으므로 데이터를 더 빠르게 전송할 수 있다.

지속 커넥션 vs 병렬 커넥션

병렬 커넥션은 여러 객체가 있는 페이지를 빠르게 전송하지만 몇가지 단점이 있다.

  • 각 트랜잭션마다 새로운 커넥션을 맺고 끊기 때문에 시간과 대역폭이 소요된다.
  • 새로운 커넥션은 가각 TCP의 느린 시작때문에 성능이 떨어진다.
  • 실제로 연결할 수 있는 병렬 커넥션의 수에는 제한이 있다.

지속 커넥션은 병렬 커넥션에 비해 몇가지 장점이 있는데, 커넥션을 맺기 위한 사전 작업과 지연을 줄여주고, 커넥션 수를 줄여준다. 다만, 지속 커넥션을 잘못 관리할 경우, 연결된 상태로 있는 커넥션이 쌓이게 될 수 있다.

파이프라인 커넥션

지속 커넥션을 통해 요청을 파이프라이닝 할 수 있다. 여러 개의 요청은 응답이 도착하기 전까지 큐에 쌓이는데 첫번째 요청이 서버에 전달되면, 거기에 이어 다음 요청들이 전달될 수 있다. 이렇게 하면 대기 시간이 긴 네트워크 상황에서 네트워크상의 왕복으로 인한 시간을 줄여서 성능을 높일 수 있다.

다만 파이프라인에는 여러가지 제약 사항이있다.

  • 클라이언트는 커넥션이 지속 커넥션인지 확인하기 전에는 파이프라인을 이어서는 안된다.
  • HTTP 응답은 요청 순서와 같게 와야한다. HTTP 메시지는 순번이 매겨져있지 않기 때문에 응답이 순서없이 오면 순서에 맞게 정렬시킬 방법이 없다.
  • 클라이언트는 커넥션이 끊어지더라도, 완료되지 않은 요청이 파이프라인에 있으면 언제든 요청을 보낼 수 있어야 한다.
  • 클라이언트는 POST요청같이 반복해서 보낼경우 문제가 생길 수 있는 요청은 파이프라인을 통해 보내면 안된다. 에러가 생겼을 경우 파이프 라인중 어떤 요청이 처리되었는지 확인 할 수 없기 때문이다. 비멱등 요청을 파이프라인 커넥션으로 보내면 안된다.

커넥션 끊기

클라이언트, 서버, 프록시는 언제든 TCP 전송 커넥션을 끊을 수 있다.

때문에 HTTP애플리케이션은 예상치 못하게 커넥션이 끊어졌을 때 적절히 대응할 수 있는 준비가 되어 있어야 한다. 클라이언트가 트랜잭션을 수행중에 전송 커넥션이 끊긴다면, 클라이언트는 그 트랜잭션을 재시도 하더라도 문제가 없아면 커넥션을 다시 맺고 한번더 전송을 시도해야한다.

어떤 요청이 전송 되었지만 응답이 오기 전에 커넥션이 끊기면 클라이언트는 서버에서 얼마만크 요청이 처리 되었는지 알수 없기 때문에 비멱등 메서드들은 반복을 피해야한다.

graceful shutdown

애플리케이션은 TCP입력채널과 출력채널 중 둘다 끊거나 하나만 끊을 수 있는데, 다른 HTTP 애플리케이션과 통신 할 때, 연결되 있는 기기들이 예상치 못한 쓰기 에러를 발생하는 것을 예방하기 위해 절반 끊기를 사용해야 한다.

클라이언트에서 더는 데이터를 보내지 않을 것임을 확신 할 수 없는 이상 커넥션의 입력 채널을 끊는 것은 위험하다.

그렇기 때문에 HTTP 커넥션을 끊는 일반적인 방법은 애플리케이션에서 자신의 출력 채널을 끊고 다른 쪽에 있는 기기의 출력 채널이 끊기는 것을 기다리는 것이다.(자세한 방법은 4-way Handshaking)

profile
조금씩,하지만,자주

0개의 댓글

관련 채용 정보