https://drive.google.com/file/d/17GbQ3VD2Wm3K288YILzRBCcFGSFM-WY6/view?usp=drive_link
tcp = 신뢰할 수 있는 데이터 전송 통로
- 순서에 맞게, 정확히 전달
HTTP 네트워크 프로토콜 스택
- HTTP
- (TLS or SSL)
- TCP
- IP
- Network Interfaces
HTTP는 현재 연결되어 있는 TCP 커넥션을 통해서 메시지 데이터의 내용을 순서대로 보냄.
- IP 패킷 ← 이란 봉투에 담아서 인터넷을 통해 데이터를 전달함.
- TCP 세그먼트 - 데이터 스트림을 잘게 나눔
→ 이 모든 과정은 TCP 소프트웨어에 의해 이루어지며, 프로그래머에게 보이지 않음
tcp socket programming
- socket api를 사용
- http 프로그래머 눈에 tcp 내부에서 일어나는 동작이 보이지 않게 함
tcp 커넥션 식별값
<발신지 IP 주소>, <발신지 포트번호>, <수신지 IP주소>, <수신지 포트>
여러 개의 커넥션이 존재
- 같은 IP 주소 or 포트 번호를 가리킬 수. 있음
- but → ip, port 모두 동일한 경우 x
클-서 TCP 소켓 인터페이스를 사용하여 상호작용하는 방법
클라이언트
C1 : IP 주소와 포트를 얻음
- socket 생성
- 서버의 IP 포트로 연결(서버는 소켓 만들고 포트로 묶은 뒤 연결을 기다리고있었음)
- 성공적 연결
- HTTP 요청을 보냄
- HTTP 응답 대기
- S7 → http 응답 처리
- 커넥션 close
서버
- 새로운 소켓을 만든다
- 80포트로 소켓을 묶음
- 소켓 커넥션 허가
- 커넥션 대기
- C3 서버의 ip, port로 연결 → 애플리케이션 커넥션 통지
- C4 연결 성공 ↔ 요청 read 시작
- C5 요청 전송 → 요청 메시지 처리
- http 응답 write
- 커넥션 close
tcp 성능에 대한 고려
HTTP 트랜잭션 지연
- DNS 이름 분석 : 방문한 적이 없는 호스트는 변환하는 데 시간이 걸림
- 연결 : 커넥션 요청 to 서버 ~ 커넥션 허가 응답 대기
- tcp 파이프를 통한 요청 ~ 처리 ~ 응답에 소요되는 시간
- 웹 서버가 응답을 보내는 것도 시간 소요됨
→ 하드웨어의 성능, 네트워크와 서버의 전송 속도, 요청과 응답 메시지의 크기, 클라이언트와 서버 간 거리
성능 관련 중요 요소
tcp 커넥션 핸드셰이크 지연
- 핸드셰이크 순서
- SYN 패킷 전송 → : 커넥션 생성 요청
- ← SYN + ACK ⇒ 커넥션 요청 허가
- 확인 응답(ACK) → : 커넥션이 잘 맺어졌음
- 오늘날 - ACK + 요청(GET ..) 전송 가능 → piggyback
- HTTP 프로그래머는 이런 내부 과정을 보지 못하지만,
- 크기가 작을수록 핸드셰이크로 인한 지연이 눈에 크게 띈다.
TCP의 편승(piggy back) 확인응답(acknowledgement)을 위한 확인응답 지연 알고리즘
- 성공적인 데이터 전송 → tcp만의 확인체계
- 순번, 데이터 무결성 체크섬
- 세그먼트를 온전히 받으면 확인응답 패킷 반환 to 송신자
- 특정 시간 안에 받지 못하면 재전송(송신자)
- 편승 → ack 패킷 크기 작음
- 효율적인 네트워크 사용
- 확인응답 지연 알고리즘 : 송출할 확인응답을 특정 ㅅ
- HTTP 동작 방식 (요청과 응답) → 편승 기회를 감소시킴
tcp 느린 시작(slow-start) - 인터넷 혼잡 제어
- 커넥션은 시간이 지나면서 자체적으로 ‘튜닝’됨
- 처음엔 커넥션의 최대 속도를 제한하고 데이터가 성공적으로 전송됨에 따라서 속도 제한을 높여나감
- 인터넷의 급작스러운 부하와 혼잡을 방지함
- 한번에 전송할 수 있는 패킷의 수를 제한
- opening the congestion window : ack를 받으면 보낼 수 있는 패킷의 양이 늘어남
- 1개 → 2개 → 4개 (패킷 각각에 대한 ack를 받음) → 8 → ..
- 새로운 커넥션은 튜닝된 커넥션보다 느리다.
혼잡 제어
- 혼잡 윈도우 크기를 처음에 1로 제한
- 지수적 증가(cwnd=cwnd+1) → 선형적 증가(cwnd=cwnd+1/cwnd, congestion avoidance)
https://developer.mozilla.org/en-US/docs/Glossary/TCP_slow_start
https://www.researchgate.net/publication/262068525_Frequent_and_Systematic_Timing_Enhancement_of_Congestion_Window_in_Typical_Transmission_Control_Protocol
RFC 5681: TCP Congestion Control
nagle 알고리즘 - 데이터를 한번에 모아 전송
- 세그먼트가 최대 크기가 아니면 전송하지 않음
- 확인응답을 대기 → 확인응답 지연과 같이 쓰이면 형편없이 동작함
- TCP_NODELAY → 네이글 알고리즘 비활성화
- 대신에 작은 패킷이 생기지 않도록 큰 크기의 데이터 덩어리를 만들어야 함
TIME_WAIT 지연과 포트 고갈
- tcp 커넥션의 종단에서 커넥션을 끊으면, 종단에서는 커넥션의 ip 주소와 포트 번호를 메모리의 작은 제어영역에 기록해 놓는다.
- 같은 주소와 포트를 사용하는 새로운 tcp 커넥션이 일정 시간 동안 생성되지 못하도록 하기 위함
- 2분 이내 또 생성 방지
- 2MSL → 세그먼트 최대 생명주기의 두 배 정도
- 이전 커넥션의 패킷이 그 커넥션과 같은 연결 값으로 생성된 커넥션에 삽입되면, 패킷은 중복되고 TCP 데이터는 충돌할 것
- 클라이언트 - 웹서버 - API 서버 구조
- 하나의 클라이언트로부터 요청을 받아서 여러 대의 API 서버에게 요청을 보내는 웹 서버라면
- <발신지 IP 주소, **발신지 포트**, 목적지 IP 주소, 목적지 포트> -> 이 중 발신지 포트만 변경 가능
- API 서버 한 대에 요청할 때마다 로컬 포트를 사용하게 됨.
사용가능한 로컬포트 = 30000 API 서버의 개수 = 2 TIME_WAIT 값 = 2MSL(초) = 60s(가정) 초당 최대 처리 가능한 요청 수 = 30000%2%60 = 250 API 서버가 10개라면? 초당 최대 처리 가능한 요청 수 = 30000%10%60 = 50 250 -> 60으로 처리 가능한 요청 수가 줄어듬
- 단순히 로컬 포트의 제한 때문에 웹 서버의 처리량이 줄어듦.
- 커넥션 유지 및 재활용
- 커넥션이나 제어 블록이 너무 많이 생기면 극심하게 느려지는 운영체제도 존재함.
HTTP 커넥션 관리
Connection 헤더
두 개의 인접한 HTTP 애플리케이션이 현재 맺고 있는 커넥션에만 적용될 옵션을 지정
- HTTP header 필드명 → 커넥션에만 해당되는 헤더들 나열
- 임시적인 토큰 값 → 커넥션에 대한 비표준 옵션
- close → 작업이 완료되면 커넥션이 종료되어야 함.
Hop 별 헤더
- Proxy-Authenticate
- Proxy-Connection
- Transfer-Encoding
- Upgrade
→ 수신자는 이 헤더를 다음 hop으로 전달하지 말아야 함.
순차적 트랜잭션 지연
- 사용자는 여러 개의 이미지가 동시에 로드되는 것을 더 좋아함(심리적)
- 모든 객체를 내려받기 전까지 텅 빈 화면만 보여줌.
커넥션 성능 향상
병렬 커넥션
여러 개의 TCP 커넥션을 통한 동시 HTTP 요청
- 네 개의 이미지를 병렬로 내려받기
- 지연시간 겹치기 → 감소
- 대역폭을 한 커넥션이 다 사용 x
단점
- 대역폭이 좁을 때 대부분의 시간을 데이터를 전송하는데만 사용
- 수백개의 커넥션 → 부하발생 ⇒ 대부분 4개로 제한(적은 수)
→ 커넥션을 맺는 지연, 느린시작 지연, 실제 개수 제한 등의 단점이 존재함.
지속 커넥션
- 사이트 지역성 : 같은 웹사이트에 여러 개의 커넥션을 맺어서 요청한 서버에 또 요청
- 처리가 완료된 후에도 계속 커넥션이 맺어져있는 상태
- 튜닝된 커넥션 유지 → slow start 없음
단점
- 계속 연결된 커넥션이 쌓이면 불필요한 리소스 소모 발생.
→ 지속+병렬이 가장 효과적
Keep-Alive
http/1.1 명세에서는 빠짐.
- Connection:Keep-Alive 헤더
- 응답에 포함시키지 않으면 이를 받은 클라이언트는 keep-alive를 지원하지 않으며, 서버 커넥션을 끊을 것이라 추정함.
- 엔티티 본문의 길이를 알 수 있어야 커넥션을 유지 가능함
- Content-Length + multipart media type
- content-length + chunked transfer encoding
- 동적으로 생성되는 콘텐츠의 지속 커넥션 허용
- To allow servers to begin transmitting dynamically generated content before knowing the total size of that content, HTTP 1.1 supports chunked encoding. This technique is widely used in music and video streaming and other industries. Chunked encoding eliminates the need of knowing the entire content length before sending a portion of the data, thus making the server looks more responsive.
- 트랜잭션이 끝나는 시점에 기존 메시지의 끝과 새로운 메시지의 시작점을 정확히 알 수 없음.
파이프라인 커넥션
- 지속커넥션을 통해서 요청을 파이프라이닝 할 수 있음
- 응답은 요청 순서대로. → 순번이 매겨져 있지 않음
- 완료되지 않은 요청이 파이프라인에 있으면 커넥션이 끊어지더라도 다시 요청을 보낼 준비가 되어있어야 함.
- POST 같은 비멱등 요청은 파이프라인을 통해서 보내면 안됨 → 에러 발생 시 보낸 요청 중 어떤 것들이 서버에서 처리되었는지 알 수 없음.
커넥션 끊기
마음대로 → 임의로 끊음
실제 전달된 엔티티 길이와 content-length 값이 일치하지 않거나 헤더 자체가 없으면 데이터의 정확한 길이를 서버에게 물어봐야 함.
- 수신자 = 캐시 프락시 → 응답 캐시 x
- 프락시는 content-length를 정정하지 말고 받은 그대로 전달
요청은 했는데, 응답이 오기 전에 커넥션이 끊김 → 클은 서버에서 얼마나 요청이 처리되었는지 전혀 알 수 없음.
- 온라인 주문 POST 등의 요청은 반복을 피해야 함.
- GET, HEAD, PUT, DELETE, TRACE, OPTIONS → 멱등
- 비멱등인 요청 자동 재시도 x → 요청 보내기 의사를 묻는 대화상자
우아한 커넥션 끊기
커넥션의 입력 채널을 끊는 것은 위험함.
클라이언트가 이미 끊긴 입력 채널에 데이터 전송 → TCP Connection Reset by peer 메시지를 클라이언트에 보낸다.
- 입력 버퍼에 있는 데이터를 지움.
- 아직 읽히지 않은 응답 데이터 사라짐.
'HTTP' 카테고리의 다른 글
HTTP 완벽 가이드 스터디 (6) (0) | 2024.10.08 |
---|---|
HTTP 완벽 가이드 스터디 (5) (0) | 2024.10.03 |
HTTP 완벽 가이드 (3) (0) | 2024.10.02 |
HTTP 완벽 가이드 스터디 (2) (0) | 2024.10.02 |
HTTP 완벽 가이드 스터디 (1) (0) | 2024.10.02 |