티스토리 뷰

* 본 게시글은 <HTTP 완벽 가이드> 서적을 적극 참고하여 작성하였습니다.

 

# TCP 커넥션

전세계 모든 HTTP 통신은 패킷 교환 프로토콜들의 계층화된 집합인 <TCP/IP>를 통해 이루어진다.

- TCP 커넥션은 메시지가 손실되거나 순서 변경 없이 온전하게 전송되는 것을 보장하는 신뢰할만한 통신방식이다.

 

1. 브라우저가 URL에 담긴 호스트명 추출

2. DNS 서버를 거쳐 자연어로 적힌 호스트명을 IP주소로 변환

3. 포트번호 확인

4. 브라우저와 서버 간 TCP 커넥션을 연결한다 (3 hand-shake)

5. 브라우저와 서버 간 요청 - 응답 메시지를 주고받는다

6. 커넥션 종료.

 

<HTTP와 HTTPS 프로토콜의 차이>

HTTP와 HTTPS의 차이점

 

- HTTP는 기존의 TCP/IP 4계층을 이용하는 방식 (IP + TCP + HTTP)

- HTTPS는 HTTP와 TCP 사이에 "SSL" 암호화 계층이 추가되어 보안이 더욱 향상된 프로토콜.

 

 

<TCP가 메시지를 보내는 방법>

- TCP는 "세그먼트" 단위로 데이터 스트림을 쪼개어 "순서대로" 전송한다.

김영한 강사님 강의자료 중 일부

HTTP 계층에서 만들어진 전송 데이터를 

-> TCP 계층에서 TCP 세그먼트로 감싸고 (TCP 포트번호, 순서/무결성 검증 정보, 제어 플래그 등..)

-> IP 계층에서 IP 패킷에 감싸고 (발신지 IP주소, 목적지 IP주소, 크기 등..)

-> 데이터링크 계층에서 프레임을 씌운 뒤 다른 네트워크로 패킷을 전송한다.

 

* 컴퓨터는 항상 TCP 커넥션을 여러개 가지고 있다. 이를 각각 구분하기 위해 필요한게 <포트번호>.

* TCP 커넥션은 <발신지 IP주소, 발신지 포트, 수신지 IP주소, 수신지 포트> 4가지 값으로 유일하게 식별한다.

 (= 4가지가 모두 같은 커넥션이 두개 이상 존재할 수 없다.)

 

 

# HTTP 트랜잭션

HTTP 트랜잭션이란: 요청 - 응답이 모두 처리될 때 까지 걸리는 하나의 과정을 통틀어서 일컫는 말.

 

HTTP 트랜잭션 흐름

위 사진을 보면 알 수 있겠지만, 실제로 서버 단에서 트랜잭션을 처리하는 시간은 전체 트랜잭션에 소요되는 시간 중에서 상당히 짧고, HTTP 트랜잭션이 처리되는 대부분의 시간은 TCP 커넥션을 맺고 요청/응답 메시지를 전송하는데 대부분의 시간이 소요된다.

 

=> HTTP 트랜잭션이 지연되는 이유는 대부분 TCP 지연때문에 발생한다.

 

[HTTP 트랜잭션이 지연되는 이유]

1. 호스트를 DNS 서버에서 IP 주소로 바꿔오고 포트번호도 알아내는데 시간이 소요됨

(단, 캐시가 되어있을 경우 빠르게 처리가능)

 

2. TCP의 고질적인 문제인 3-way handshake 과정

(SYN(→) -> SYN+ACK(←) -> ACK(→)), 대부분의 지연이 여기서 발생.

 

3. IP 패킷이 오고가는데도 시간이 걸림

 

4. 서버단에서 너무 많은 작업을 처리하고 있을 경우 처리시간도 걸림

 

+) 추가적인 TCP 성능에 영향을 끼치는 요소

> TCP의 느린 시작(slow start)

- TCP 커넥션은 시간이 지나면서 자체적으로 "튜닝" 과정을 거쳐 전송속도를 더 빠르게 조절할 수 있다

- 갑작스러운 부하와 혼잡을 방지하는 용도. 혼잡제어.

- 뒤에서 다룰 "지속 커넥션"과 연결하여 사용.

 

> 데이터를 쌓아놨다 한방에 보내는 Nagle 알고리즘

- TCP 세그먼트가 너무 잘게 쪼개진 상태로 수많은 패킷이 전송되면 네트워크 성능에 악영향을 준다.

- 따라서 패킷을 일정 크기만큼 쌓아놨다가 모였다 싶으면 보낸다.

 

> TIME_WAIT 지연과 포트 고갈

- TCP 커넥션이 끊어지고 난 이후 일정 시간동안 같은 TCP 커넥션(수신자 IP, 포트번호가 같은) 이 다시 연결되지 않도록 한다.

- TIME_WAIT에 대해 검색해보니까 꽤 많은 자료들이 있는데 기초수준에서 보기에는 조금 어려운 것 같아서..

나중에 공부해볼것!

(https://sunyzero.tistory.com/198)

(https://kuaaan.tistory.com/118)

 

옆길로 잠깐 새는 [TIME_WAIT 대략적인 이해]

TIME_WAIT가 존재하는 이유 - 메시지 손실 없이 안정적인 커넥션 종료를 위해!

https://kuaaan.tistory.com/118

TCP 커넥션을 맺을때도 3-way handshake 과정을 거치지만

TCP 커넥션을 끊을때에도 4-way handshake 과정을 거친다!

(중요한 부분) 먼저 연결을 끊겠다 요청을 한 쪽(active close)에 "TIME_WAIT" 헤더가 남는다

1. 클라이언트 단에서 TCP 연결을 끊자며 FIN 세그먼트를 서버에 날린다

2. 서버 단에서 클라이언트의 요청 수신. 확인했다면서 ACK 세그먼트를 클라이언트에 날린다

3. 서버 단에서 연결종료 준비가 다 되었다면 FIN 세그먼트를 클라이언트에 날린다

4. 클라이언트 단에서 서버의 준비완료 세그먼트를 받고 마지막 ACK 세그먼트를 날려준다.

(TCP 커넥션 종료가 가능한 상태가 되었다)

 

* 다만, 네트워크를 통해 전송되고 있던 데이터가 다른 이유로 인해 FIN 세그먼트보다 늦게 도착하는 경우

데이터가 도착했을때는 이미 TCP 커넥션이 끊어진 상태이기 때문에 데이터가 유실될 수 밖에 없다.

 

이러한 현상을 방지하고 온전한 데이터 전송을 보장하기 위해 TIME_WAIT 대기시간을 두어 혹시나 모를 데이터 유실을 방지하는 것!!!

 

* 여기서 중요한건, 먼저 active close한 쪽에 TIME_WAIT 헤더가 남는다고 했는데, 클라이언트 단에서 남는건 큰 문제가 없지만 서버 단에 TIME_WAIT 헤더가 남아서 쌓이는 경우 사용가능한 포트가 고갈되어 서버에 부하를 주고, 새로운 연결도 받지않는 사태를 유발할 수 있다. (TIME_WAIT 대기시간 기본 2분).

이를 방지하기 위해 서버단에서 먼저 active close 하는게 아니고, 서버에서 클라이언트에게 너가 먼저 active close 하라고 요청을 보내서 클라이언트가 먼저 active close 하도록 하게 한다 카더라는데. 자세한건 .

 

-------

# HTTP 커넥션 기법

[순차적인 트랜잭션 처리 - 구식]

 

직렬 처리방식

웹페이지에 3개의 이미지를 받아와야 한다고 하자.

- 브라우저가 이 페이지를 그리기 위해서는 4개의 트랜잭션을 연결해야 한다.

(하나는 HTML 페이지를 받기 위해, 나머지 3개는 이미지를 받아오기 위해)

- 직렬 순차처리를 하면 하나의 트랜잭션이 처리되는 동안 나머지는 그냥 빈 화면으로 대기하고 있게된다..

- 이를 방지하기 위한 최신 기법들을 사용하도록 하자!

 

[병렬 커넥션, Parallel Connection]

 

클라이언트가 여러개의 커넥션을 맺도록 
병렬 처리방식

클라이언트가 한번에 여러 커넥션을 맺음으로써 한방에 여러 트랜잭션을 병렬로 처리할 수 있게 한다.

- 서버에 과도한 부담을 줄 수 있음

- 실제로 연결할 수 있는 병렬 커넥션의 수는 제한되어있다 (기본 4개)

 

[지속 커넥션, Persistent Connection]

일반적으로 서버에 HTTP 요청을 하기 시작한 애플리케이션은 웹페이지 내의 이미지 등을 가져오기 위해서 그 서버에 다시 요청을 하게 될 가능성이 높다. => 사이트의 지역성(site locality)

-> 트랜잭션 처리가 끝난 이후에도 TCP 커넥션을 끊지 않고 유지함으로써 HTTP 요청에 재사용할 수 있도록 한다!

-> 클라이언트나 서버가 커넥션을 끊기 전까지는 트랜잭션 간에도 커넥션을 유지한다.

 

- 커넥션을 맺기 위한 사전작업과 지연을 줄여주고(3-way handshake)

+ 튜닝된 커넥션을 유지하기 때문에 속도가 더 향상된다.

- 지속 커넥션은 병렬 커넥션과 함께 사용될 때 가장 효과적이다

지속 커넥션

- 커넥션을 맺고 끊는데 필요한 시간이 줄어들어 처리시간이 매우 단축된다.

 

"keep-alive" 커넥션

Connection:Keep-Alive 헤더가 포함된 메시지를 받으면 클라이언트와 서버는 TCP 커넥션을 끊지 않고 연결을 유지한다.

- HTTP/1.0 에서는 기본 헤더가 아니다. 클라이언트는 keep-alive 커넥션을 사용하기 위해 Connection:Keep-Alive 헤더를 꼭 포함해야한다.

- 클라이언트는 서버로부터 받은 메시지에 Keep-Alive 헤더가 없는 것을 보고 서버가 응답 후에 커넥션을 끊을 것임을 알 수 있다.

- 커넥션이 끊어지기 전에 정확한 Content-Length 길이를 알고있어야 한다.

>> 위에서 본것처럼 손실없는 메시지 전송을 보장하기 위함.

 

* Keep-Alive 커넥션이 무리하게 쌓이면 또 서버에서 새로운 연결을 받지 못하는 상황이 올 수 있기 때문에 옵션을 통해 최대 연결시간(timeout), n개의 트랜잭션이 처리될때 까지만 유지(max)를 설정한다.

Connection: Keep-Alive
Keep-Alive: max=5, timeout=120

 

* HTTP/1.1 부터는 기본적으로 TCP 커넥션을 지속 커넥션으로 맺는다 (Keep-Alive 커넥션을 지원하지 않음)

- 커넥션을 끊기 위해서는 Connection: close 헤더를 명시해야한다.

- close 헤더가 없으면 응답 후에도 커넥션을 계속 유지하자는 것으로 간주한다.

- 클라이언트는 해당 커넥션으로 추가적인 데이터를 전송하지 않을것이라면 마지막 요청에 close 헤더를 보내야한다.

- 애플리케이션은 중간에 끊어지는 커넥션을 복구할 수 있어야한다. (요청을 다시 보낼 준비가 항상 되어있어야함)

- 지속 커넥션은 서버의 과부화를 방지하기위해 1인당 2개정도만 허용한다.

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함