[4장] 커넥션 관리

Haeseo Lee·2023년 3월 7일
0
post-thumbnail

TCP Connection


  • 전 세계 모든 통신은 패킷 교환 네트워크 프로토콜들의 계층집합인 TCP/IP를 통해 이루어짐

→ 일단 커넥션이 맺어지면 client-server 간에 주고받는 메시지들은 안전하게 전달

(손실/손상 X, 순서 바뀜X)

  • 구성
    • 발신지 IP주소

    • 발신지 port

    • 수신지 IP주소

    • 수신지 port

      ⇒ 위 네 가지 값으로 유일한 커넥션 생성

TCP 커넥션이 이루어지는 예

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

1) 브라우저가 URL에서 호스트 명 추출: www.joes-hardware.com:80

2) DNS로 호스트 명에 대한 IP 주소를 찾음

3) TCP 커넥션 생성: 호스트 IP 주소와 포트 번호80

4) 브라우저가 서버로 HTTP GET 요청 메시지 전송

5) 서버가 브라우저로 HTTP 응답 메시지 전송

6) 브라우저가 응답 메시지 수신

7) 커넥션 종료


TCP 스트림


  • HTTP는 현재 연결되어 있는 TCP 커넥션을 통해서 메시지 데이터의 내용을 순서대로 보냄

  • TCP는 segment 단위로 데이터 스트림을 잘게 나누고 IP 패킷에 담아 전달

IP 패킷

  • IP 패킷 헤더 (20byte)
  • TCP Segment 헤더(20byte)
  • TCP 데이터 조각

TCP socket programming


socket API

  • TCP endpoint 구조 생성
  • 원격 서버의 TCP endpoint에 데이터 스트림을 읽고 쓸 수 있음
  • 예시
    • socket() : 새로운 익명 소켓 생성 (미연결)
    • bind() : 소켓에 ip주소, port번호 할당
    • connect() : 로컬 소켓과 원격 host/port 사이에 TCP 커넥션 생성
    • listen() : 소켓 커넥션 허가
    • accept() : 다른 소켓으로부터의 커넥션 기다림
    • read() : 소켓으로부터 버퍼에 n-byte 읽기 시도
    • write() : 소켓으로부터 버퍼에 n-byte 쓰기 시도
    • close() : TCP 커넥션 종료

HTTP 트랜잭션 지연


HTTP 트랜잭션을 지연시킬 수 있는 원인

  • 방문한 적 없는 호스트
    ⇒ DNS로 호스트 명을 IP 주소로 변환하는 데 시간 소요
  • 새로운 TCP 커넥션 설정 시간
    ⇒ 클라이언트가 TCP 커넥션 요청을 서버에 보내 응답을 회신받는 데 시간 소요
  • 서버에서의 요청 처리 시간
  • 서버가 HTTP 응답을 보내는 데 걸리는 시간
  • etc…

TCP 커넥션의 handshake 지연


  • 새로운 TCP 커넥션을 맺을 경우 TCP 소프트웨어가 커넥션 설정을 위해 연속으로 패킷 교환

TCP 커넥션 handshake 순서

1) 새 TCP 커넥션 생성을 위해 client가 server로 SYN(커넥션 생성 요청) 플래그를 포함한 작은 TCP 패킷을 전송

2) server가 그 커넥션 요청을 수락하게 되면 SYN + ACK 플래그를 포함한 TCP 패킷을 client에 전송

3) client가 커넥션이 잘 맺어졌음의 의미로 다시 server로 ACK를 전송
(오늘날에는 ACK와 데이터를 같이 보낼 수 있음)

  • 그러나 작은 크기의 데이터를 전송하는 데에도 커넥션이 사용된다면 이런 패킷 교환은 HTTP 성능을 저하시킬 수 있음
  • TCP의 ACK 패킷은 HTTP 요청 메시지 전체를 전달할 수 있을만큼 큰 경우 多
  • 크기가 작은 HTTP 트랜잭션은 50% 이상의 시간을 TCP 구성에 소요

ACK(확인응답) 지연


  • 각 TCP segment는 순번과 데이터 무결성 checksum을 가짐
  • 각 segment의 수신자는 segment를 온전히 받으면 작은 ACK 패킷을 반환
    • 만약 특정 시간 내로 수신자에게서 ACK 반환이 없으면 데이터 재전송
  • ACK는 크기가 작으므로 TCP는 같은 방향으로 송출되는 데이터 패킷과 ACK를 묶어서 전송

확인응답(ACK) 지연 알고리즘

  • ACK가 같은 방향으로 가는 데이터 패킷에 편승(piggyback)되는 경우를 늘리기 위한 알고리즘
  • 동작
    1) 송출할 ACK를 특정시간(보통 0.1~0.2s) 동안 버퍼에 저장
    2) ACK를 편승시킬 송출 데이터 패킷 탐색
    - 시간 내에 송출 데이터 패킷을 찾지 못하면 ACK는 별도 패킷을 만들어 전송
  • 그러나 요청-응답 방식의 HTTP 특성상 같이 송출될 패킷을 찾기 힘듦
    ⇒ ACK 지연 알고리즘으로 인한 지연 자주 발생

TCP slow start로 인한 지연


slow start (느린 시작)

  • TCP 커넥션의 초기에는 최대 속도를 제한하다가
  • 데이터가 성공적으로 전송됨에 따라 속도제한 ↑
    ⇒ 인터넷의 급작스러운 부하와 혼잡 방지
  • 한 개의 패킷 전송 → ACK 송신 → 2개의 패킷
    ⇒ opening the congestion window
  • 새로운 커넥션은 튜닝된(이미 데이터를 주고받은 적 있는) 커넥션보다 느림

Nagle 알고리즘


  • 작은 크기의 데이터를 포함한 다량의 패킷을 전송하면 네트워크 성능 ↓

Nagle 알고리즘

  • 네트워크 효율을 위해 패킷 전송 전 많은 양의 TCP 데이터를 한 덩어리로 합침
  • [참고] [RFC 896 “congestion control in IP/TCP internetworks”]
  • 동작
    • segment가 최대 크기가 되지 않으면 전송 X
    • 단, 모든 패킷이 ACK를 받았을 경우 최대 크기보다 작은 패킷 전송 허락
    • 다른 패킷들이 아직 전송 중이면 데이터는 버퍼에 저장
  • 즉, 전송되고 나서 ACK를 기다리던 패킷이 ACK를 받았거나, 전송하기 충분할 만큼의 패킷이 쌓였을 때 버퍼에 저장되어 있던 데이터 전송

Nagle 알고리즘이 야기하는 문제

  • 충분히 패킷을 채울 때까지 전송 지연
  • ACK 지연과 함께 쓰일 경우 성능 하락

해결책

  • HTTP 스택에 TCP_NODELAY 파라미터 값을 설정하여 nagle 알고리즘 비활성화 가능

TIME_WAIT 지연, 포트 고갈


TIME WAIT(커넥션 종료 지연)

  • TCP 커넥션의 endpoint 에서 커넥션 종료 시,
  • 메모리의 control block(제어 블록)에 커넥션의 IP 주소와 포트 번호 기록
    ⇒ 해당 커넥션이 일정 시간(보통 2MSL 정도) 동안 생성되지 않도록 함
    ⇒ 이전 커넥션과 관련된 패킷이 똑같은 주소/포트로 된 새로운 커넥션에 삽입되는 문제 방지

TIME WAIT가 야기하는 문제

  • client가 server에 접속할 때마다 유일한 커넥션을 생성하기 위해 새로운 발신지 port 사용
  • 그러나 사용할 수 있는 발신지 포트 수는 제한되어 있음
    • e.g) 발신지 포트 수 = 60,000
      • 2MSL초(120초) → 초당 500개로 커넥션 제한

Connection 헤더


사용하는 경우

  • HTTP client-server 사이에는 중개 서버(proxy, cache, …)가 놓일 수 있음
  • 두 개의 인접한 HTTP 애플리케이션이 맺고 있는 커넥션에 적용될 옵션을 지정해야 할 경우
  • HTTP Connection 헤더 필드에 명시된 커넥션 토큰은 다른 커넥션에 전달 X

Connection 헤더에 명시되는 세 종류의 토큰

  • HTTP 헤더 필드명
    • 이 커넥션(hop-by-hop)에만 해당되는 헤더들
  • 임시적인 토큰
    • 커넥션에 대한 비표준 옵션
  • close
    • 트랜잭션 작업 완료 시 커넥션 종료

  • HTTP 애플리케이션이 Connection 헤더와 함께 메시지를 전달받으면
    • 수신자는 송신자에게서 온 요청에 기술되어 있는 모든 옵션 적용
    • 다음 hop에 메시지 전달 전 Connection 헤더 삭제

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


  • 각 트랜잭션이 새로운 커넥션을 필요로 할 경우
    • 커넥션 생성에 발생하는 지연
    • slow start 지연 발생


HTTP 커넥션 성능을 향상시킬 방법


  • 병렬(parallel) 커넥션
  • 지속(persistent) 커넥션
  • 파이프라인(pipelined) 커넥션
  • 다중(multiplexed) 커넥션

병렬 커넥션


  • 여러 개의 TCP 커넥션을 통한 동시 HTTP 요청

페이지를 더 빠르게 내려받을 수 있음

  • 각 커넥션의 지연 시간을 겹치게
    ⇒ 총 지연 시간 ↓
  • 대역폭이 남으면 나머지 객체를 내려받는 데 사용 가능

항상 더 빠르지는 X

  • 클라이언트의 네트워크 대역폭이 좁은 경우
    ⇒ 병렬 처리 장점 X
  • 다수의 커넥션
    ⇒ 메모리 소모 ↑, 자체적인 성능 문제 발생
  • 각 트랜잭션마다 새로운 커넥션을 맺고 끊어야 하므로 시간과 대역폭 소모

실제로는

  • 브라우저: 적은 수(대부분 6-8개)의 병렬 커넥션 허용
  • 서버: 특정 클라이언트로부터 과도한 수의 커넥션이 맺어졌을 경우 임의로 끊기 가능

지속 커넥션


  • TCP 커넥션을 재활용함으로서 커넥션 연결에서 발생하는 지연 제거

site locality

  • 리소스를 요청했던 서버에 재요청할 가능성 높음
  • HTTP/1.1은 트랜잭션 처리 완료 후에도 계속 연결된 상태 유지 가능
  • slow start 지연 X, 빠르게 데이터 전송

병렬 커넥션과 비교한 장점

  • 커넥션 연결의 사전 작업과 지연 ↓
  • 튜닝된(다수의 패킷을 전송할 수 있는 권한을 얻은) 커넥션 유지
  • 커넥션 수 ↓

무조건 좋은 건 아님

  • 지연 커넥션을 잘못 관리하여 쌓이게 될 경우,
  • client와 server의 리소스에 불필요한 소모 발생

지속 커넥션 + 병렬 커넥션

  • 적은 수의 병렬 커넥션을 맺고 그것을 유지

HTTP/1.0 Keep-Alive 커넥션

  • 하나의 지속 커넥션으로 트랜잭션들 처리
  • client
    • 커넥션을 유지하고자 할 때
    • 요청에 Connection: Keep-Alive 헤더 포함
  • server
    • 다음 요청도 이 커넥션을 통해 받고자 할 경우
    • 응답 메시지에 같은 헤더 포함
  • Keep-Alive 헤더 options
    • timeout: 커넥션 유지 시간
    • max: 커넥션이 유지 동안 처리되는 HTTP 트랜잭션 수
  • 단점
    • HTTP/1.0의 proxy는 Connection 헤더를 인식하지 못해 그대로 전달 ⇒ dumb proxy

HTTP/1.1 지속 커넥션

  • 기본으로 활성화
  • 모든 커넥션을 지속 커넥션으로 취급
  • 커넥션을 종료하고자 할 경우 Connection: close 헤더 명시
  • 제한
    • 커넥션에 있는 모든 메시지가 자신의 길이 정보를 정확히 가지고 있을 때만 커넥션 지속
      • 정확한 Content-Length 값
      • 청크 전송 인코딩 (Chunked transfer encoding)
    • HTTP 1.1 proxy server는 client와 server 각각에 대해 별도의 지속 커넥션을 맺고 관리
    • HTTP/1.1 애플리케이션은 언제든지 중간에 끊어진 커넥션을 복구할 수 있어야 함
profile
잡생각 많은 인간

0개의 댓글