You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- 예제에서 buffer size를 왜 1460바이트로 설정했을까?
- Ethernet MTU 1500 바이트
TCP 성능에 대한 고려
HTTP는 TCP 위에 있는 계층이기 때문에 HTTP의 트랜잭션 성능은 그 아래 계층인 TCP 성능에 영향을 받는다.
트랜잭션을 처리하는 시간은 TCP 커넥션을 설정gkrh, 요청을 전송하고, 응답 메시지를 보내는 것에 비하면 비교적 짧다.
너무 많은 데이터를 내려받거나 복잡한 처리가 수반되는 실행이 아닌 이상 대부분의 HTTP 지연은 TCP 네트워크 지연때문에 발생한다.
HTTP 트랜잭션을 지연시키는 원인
클라이언트는 URI에서 웹 서버의 IP 주소와 포트번호를 알아내야 한다.
URI에 기술되어 있는 호스트를 방문한 적이 없는 경우 DNS를 활용해야 하고 이 과정에서 지연이 발생
클라이언트는 TCP 커넥션 요청을 서버에게 보내고 서버가 커넥션 허가 응답을 회신하기를 기다린다. (3-way handshake)
커넥션 설정 시간은 새로운 TCP 커넥션에서 항상 발생하고, 보통 1-2초의 시간이 소요되지만 수 백개의 HTTP 트랜잭션이 만들어지는 경우 소요 시간이 크게 증가한다.
커넥션이 맺어지면 클라이언트는 HTTP 요청을 새로 생성된 TCP 파이프를 통해 전송한다.
웹 서버는 데이터가 도착하는 대로 TCP 커넥션에서 요청 메세지를 읽고 처리한다.
요청 메시지가 인터넷을 통해 전달되고, 서버에 의해서 처리되는 데 까지는 시간이 소요된다.
웹 서버가 HTTP 응답을 보내는 것 역시 시간이 소요된다.
TCP 네트워크 지연
TCP 네트워크 지연은 하드웨어 성능, 네트워크와 서버의 전송 속도, 요청과 응답 메시지의 크기, 클라이언트와 서버 간의 거리에 따라 크게 달라진다.
TCP 커넥션의 핸드셰이크 지연
어떤 데이터를 전송하든 새로운 TCP 커넥션을 열게 되면 핸드셰이크 과정이 발생된다.
작은 크기의 데이터 전송에 계속해서 커넥션이 사용된다면 이러한 패킷 교환은 HTTP 성능을 크게 저하시킬 수 있다.
3-Way handshake
송신자(Client)와 수신자(Server) 모두 데이터를 전송할 준비가 되었다는 것을 보장하며, 데이터 전달 시작전에 상대가 준비되었다는 것을 알 수 있게 한다.
Client > Server : SYN (저 세션연결 시작할게요 서버님)
클라이언트가 서버에게 SYN(SYNchronization)플래그를 보낸다. (sequence: x)
Server > Client : ACK (어 연락받았어 잘들리네) SYN (나도 연결할게)
서버가 SYN(x)을 받고, 클라이언트로 받았다는 신호인 ACK(ACKnowledgement) 와 SYN 플래그를 보낸다. (sequence: y, ACK: x + 1)
Client > Server : ACK (넵 알겠습니당 저도 잘들려여)
클라이언트는 서버의 응답으로 ACK(x + 1)와 SYN(y) 플래그를 받고, ACK(y+1)를 서버로 보낸다.
cf. Sequence Number를 랜덤으로 생성하는 이유?
3 way handshake 과정에서 클라이언트는 SYN 플래그를 보낼 때 Sequence number에 랜덤으로 숫자 값을 담아서 전송한다.
이러한 초기 sequece number를 ISN이라고 한다.
그렇다면 ISN이 0부터 시작하지 않고 난수를 생성해서 값을 설정하는 이유는 무엇일까?
Connection을 맺을 때 사용하는 포트(port)는 유한 범위 내에서 사용하고 시간이 지남에 따라 재사용된다.
따라서 두 통신 호스트가 과거에 사용된 포트 번호 쌍을 사용하는 가능성이 존재한다.
서버 측에서는 패킷의 SYN을 보고 패킷을 구분하게 되는데 난수가 아닌 순차적인 number가 전송된다면 이전의 connection으로부터 오는 패킷으로 인식할 수 있다.
이러한 문제가 발생할 가능성을 줄이기 위해서 난수로 ISN을 설정한다.
4-Way handshake
송신자(Client)와 수신자(Server) 모두 세션을 종료함을 인지한다.
세션종료를 의미하는 FIN 패킷을 서버측에서 받더라도, 패킷유실이나 라우팅지연으로 인한 재전송으로 인한 잔여데이터를 위해 Client는 서버측에서 FIN을 수신하더라도 일정시간(default 240 sec) 동안 ACK 패킷을 서버측에 보내지않고 잉여 패킷을 기다린다. (TIME_WAIT)
인터넷 자체가 패킷 전송을 완벽히 보장하지 않기 때문에 TCP는 성공적인 데이터 전송을 보장하기 위해서 자체적인 확인 체계를 가진다.
라우터는 과부하가 걸렸을 때 패킷을 마음대로 파기할 수 있다.
각 TCP 세그먼트는 순번과 데이터 무결성 체크섬을 가진다. 세그먼트의 수신자는 세그먼트를 온전히 받으면 확인응답 패킷을 송신자에게 반환한다.
송신자가 특정 시간 안에 확인응답 메시지를 받지 못 하면 패킷이 파기되었거나 오류가 있는 것으로 판단하고 데이터를 다시 전송한다.
확인응답은 크기가 작기 때문에, TCP는 같은 방향으로 송출되는 데이터 패킷에 확인응답을 편승(piggyback)시킨다.
네트워크를 좀 더 효율적으로 사용하기 위해 송출하는 데이터 패킷과 확인응답을 하나로 묶어서 전송한다.
확인응답을 보내야 하는데 당장 송출된 데이터가 없다면 특정 시간동안(100~200ms) 버퍼에 저장해두고, 송출할 데이터 패킷을 기다린다.
특정 시간 이후동안 송출할 패킷을 찾지 못 한다면 별도의 패킷을 생성하여 확인응답을 전송한다.
HTTP 동작 방식의 특성을 고려할 때 편승할 패킷을 찾으려고 하는 경우 해당 방향으로 송출될 패킷이 많지 않기 때문에 확인응답 지연 알고리즘에 의한 지연이 자주 발생한다.
OS에 따라 다르지만 지연의 원인이 되는 확인응답 지연 관련 기능을 수정하거나 비활성화할 수 있다.
TCP 느린 시작(slow-start)
TCP의 데이터 전송 속도는 TCP 커넥션이 만들어진지 얼마나 지났는지에 따라 달라질 수 있다.
TCP 커넥션은 시간이 지나면서 자체적으로 튜닝되어서, 처음에는 커넥션의 최대 속도를 제한하고 데이터가 성공적으로 전송됨에 따라서 속도 제한을 높여나간다.
이렇게 조율하는 것을 TCP slow-start라고 부르고, 이를 통해 인터넷의 급작스러운 부하와 혼잡을 방지한다.
이러한 혼잡제어 기능 때문에 새로운 커넥션은 이미 어느 정도 데이터를 주고받은 튜닝된 커넥션보다 느리다. 튜닝된 커넥션은 더 빠르기 때문에 HTTP에는 이미 존재하는 커넥션을 재사용하는 기능이 있다. -> 지속 커넥션
혼잡제어 관련 내용은 후술
네이글(nagle) 알고리즘과 TCP_NODELAY
어떠한 크기의 데이터든지 TCP 스택으로 전송하게 되면 TCP 세그먼트를 구성해야 한다.
하지만 매우 작은 크기의 데이터를 전송하는 경우에도 40바이트 정도의 플래그와 헤더를 포함하여 전송하기 때문에 작은 크기의 데이터를 포함한 많은 수의 패킷을 전송하는 경우 네트워크 성능이 떨어진다.
이를 해결하기 위해 패킷을 전송하기 전에 많은 양의 TCP 데이터를 한 개의 덩어리로 합치고, 이 알고리즘이 네이글 알고리즘이다.
네이글 알고리즘은 세그먼트가 최대 크기(이더뎃 기준 MTU 1500바이트)가 되지 않으면 전송을 하지 않는다.
다만 다른 모든 패킷이 확인응답을 받았을 경우에는 최대 크기보다 작은 패킷의 전송을 허락한다.
다른 패킷들이 아직 전송 중이면 데이터의 버퍼에 저장된다. 전송되고 나서 확인응답을 기다리던 패킷이 확인응답을 받았거나 전송하기 충분할 만큼의 패킷이 쌓였을 때 버퍼에 저장되어 있던 데이터가 전송된다.
네이글 알고리즘은 HTTP 성능과 관련해서 여러 문제를 발생시킨다.
크기가 작은 HTTP 메시지는 패킷을 채우지 못 하기 때문에 계속해서 데이터를 기다리며 지연된다.
네이글 알고리즘은 확인응답 지연과 함께 쓰일 경우 확인응답이 도착할 때까지 데이터 전송을 멈추고 있는 반면, 확인응답 지연 알고리즘은 확인응답을 100-200ms를 지연시킨다.
HTTP 애플리케이션에서는 HTTP 스택에 TCP_NODELAY 파라미터 값을 설정하여 네이글 알고리즘을 비활성화기도 한다.
TIME_WAIT 지연과 포트 고갈
TCP 커넥션을 끊으면, 커넥션의 종단에서는 커넥션의 IP 주수와 포트 번호를 메모리의 제어 영역에 기록해놓는다.
같은 주소와 프트 번호를 사용하는 새로운 커넥션이 일정 시간동안 생성되지 않게 하기 위함
보통 2분 정도 유지 (2MSL)
이전 커넥션과 관련된 패킷이 해당 커넥션과 같은 주소, 포트 번호를 가지는 새로운 커넥션에 삽입되는 문제를 방지하기 위함
일반적으로 2MSL이라는 종료 지연이 문제가 되지는 않지만, 성능 테스트를 하는 상황에서는 문제가 될 수 있다.
성능 측정 대상 서버는 클라이언트가 접속할 수 있는 IP 주소의 개수를 제한하고, 접속하는 컴퓨터의 수가 제한적이기 때문에 생성할 수 있는 주소와 포트 조합이 제한적이다.
TIME_WAIT으로 인해 순간순간 포트를 재활용하는 것이 불가능해진다.
cf. TCP 흐름 제어 및 혼잡 제어 (+ 오류 제어)
흐름 제어(Flow control)
송신측과 수신측의 데이터 처리 속도 차이를 해결하기 위한 기법
수신측이 송신측보다 데이터 처리 속도가 빠르면 문제없지만, 송신측의 속도가 빠를 경우 문제가 생긴다.
Flow Control은 receiver가 packet을 지나치게 많이 받지 않도록 조절하는 것
기본 개념은 receiver가 sender에게 현재 자신의 상태를 feedback 한다는 점
해결방법
Stop and Wait : 매번 전송한 패킷에 대해 확인 응답을 받아야만 그 다음 패킷을 전송하는 방법
Sliding Window (Go Back N ARQ) : 먼저 윈도우에 포함되는 모든 패킷을 전송하고, 그 패킷들의 전달이 확인되는대로 이 윈도우를 옆으로 옮김으로써 그 다음 패킷들을 전송
혼잡 제어(Congestion control)
송신측의 데이터 전달과 네트워크의 데이터 처리 속도 차이를 해결하기 위한 기법
송신측의 데이터는 지역망이나 인터넷으로 연결된 대형 네트워크를 통해 전달된다. 만약 한 라우터에 데이터가 몰릴 경우, 자신에게 온 데이터를 모두 처리할 수 없게 된다. 이런 경우 호스트들은 또 다시 재전송을 하게되고 결국 혼잡만 가중시켜 오버플로우나 데이터 손실을 발생시키게 된다. 따라서 이러한 네트워크의 혼잡을 피하기 위해 송신측에서 보내는 데이터의 전송속도를 강제로 줄이게 되는데, 이러한 작업을 혼잡제어라고 한다.
해결방법
AIMD(Additive Increase / Multiplicative Decrease)
처음에 패킷을 하나씩 보내고 이것이 문제없이 도착하면 window 크기(단위 시간 내에 보내는 패킷의 수)를 1씩 증가시켜가며 전송하는 방법
패킷 전송에 실패하거나 일정 시간을 넘으면 패킷의 보내는 속도를 절반으로 줄인다.
Slow Start (느린 시작)
AIMD 방식이 네트워크의 수용량 주변에서는 효율적으로 작동하지만, 처음에 전송 속도를 올리는데 시간이 오래 걸리는 단점이 존재
Slow Start 방식은 AIMD와 마찬가지로 패킷을 하나씩 보내면서 시작하고, 패킷이 문제없이 도착하면 각각의 ACK 패킷마다 window size를 1씩 늘려준다. 즉, 한 주기가 지나면 window size가 2배로 됨
Fast Retransmit (빠른 재전송)
패킷을 받는 쪽에서 먼저 도착해야할 패킷이 도착하지 않고 다음 패킷이 도착한 경우에도 ACK 패킷을 보냄
중복된 순번의 패킷을 3개 받으면 재전송
(혼잡한 상황이 일어난 것이므로 혼잡을 감지, window size를 줄임)
Fast Recovery (빠른 회복)
혼잡한 상태가 되면 window size를 1로 줄이지 않고 반으로 줄이고 선형증가시키는 방법
HTTP 커넥션 관리
HTTP Connection 헤더
HTTP는 클라이언트와 서버 사이에 proxy server, cache server 등과 같은 중개 서버가 놓이는 것을 허락한다.
4장 커넥션 관리
Prologue
HTTP 명세는 HTTP 메시지 포맷에 대해서 구체적으로 정의하고 있지만, HTTP 커넥션과 메시지 흐름에 대한 내용은 충분히 다루지 않고 있다.
왜? -> HTTP는 application layer protocol이고, 커넥션 및 전송과 관련된 부분은 하위 layer 기반해서 작동하기 때문
이번 장에서는 아래 항목들에 대해서 언급한다.
HTTP에 대한 내용보다는 HTTP 프로토콜을 지원하기 위한 하위 계층의 커넥션 및 기반 기술에 대해 설명
TCP 커넥션
대~~~부분(거의 모든) HTTP 통신은 TCP/IP를 통해 이루어진다.
connection이 맺어지면 peer간에 주고 받는 메시지들은 손실/손상되지 않거나 순서가 바뀌지 않고 안전하게 전달된다.
TCP의 메시지 전송
TCP 스트림은 세그먼트로 나뉘어 IP 패킷(IP datagram)을 전송한다.
HTTP는 IP, TCP, HTTP로 구성된 프로토콜 스택에서 최상위 계층이고, 여기에 보안 기능을 더한 것이 HTTPS
TCP 세그먼트
TCP 포트 번호, TCP 제어 플래그, 데이터 순서, 무결성 검사를 위한 값(checksum)
cf. https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=4717010&logNo=60212483299
최대 패킷 크기는 65,535바이트(2^16) - UDP
TCP 유지
TCP 소켓 프로그래밍
cf. https://github.com/Effective-Java-Camp/http-the-definitive-guide/tree/main/examples/tcp-socket
TCP 성능에 대한 고려
트랜잭션을 처리하는 시간은 TCP 커넥션을 설정gkrh, 요청을 전송하고, 응답 메시지를 보내는 것에 비하면 비교적 짧다.
너무 많은 데이터를 내려받거나 복잡한 처리가 수반되는 실행이 아닌 이상 대부분의 HTTP 지연은 TCP 네트워크 지연때문에 발생한다.
HTTP 트랜잭션을 지연시키는 원인
클라이언트는 URI에서 웹 서버의 IP 주소와 포트번호를 알아내야 한다.
클라이언트는 TCP 커넥션 요청을 서버에게 보내고 서버가 커넥션 허가 응답을 회신하기를 기다린다. (3-way handshake)
커넥션이 맺어지면 클라이언트는 HTTP 요청을 새로 생성된 TCP 파이프를 통해 전송한다.
웹 서버가 HTTP 응답을 보내는 것 역시 시간이 소요된다.
TCP 네트워크 지연
TCP 커넥션의 핸드셰이크 지연
3-Way handshake
Client > Server : SYN (저 세션연결 시작할게요 서버님)
Server > Client : ACK (어 연락받았어 잘들리네) SYN (나도 연결할게)
Client > Server : ACK (넵 알겠습니당 저도 잘들려여)
cf. Sequence Number를 랜덤으로 생성하는 이유?
3 way handshake 과정에서 클라이언트는 SYN 플래그를 보낼 때 Sequence number에 랜덤으로 숫자 값을 담아서 전송한다.
그렇다면 ISN이 0부터 시작하지 않고 난수를 생성해서 값을 설정하는 이유는 무엇일까?
4-Way handshake
Client > Server : FIN (저 이제 세션종료할게요 서버님)
Server > Client : ACK (어 연락받았어 잘들리네 잠만 기다려봐 보내라고 한거 마저 보내줄게)
Server > Client : FIN (일단 급한대로 다 보냈다. 확인하고 종료해줘)
Client > Server : ACK (아이고 감사합니다. 다 잘받았네여)
cf1. https://mindnet.tistory.com/entry/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-22%ED%8E%B8-TCP-3-WayHandshake-4-WayHandshake
cf2. https://yoon1fe.tistory.com/165
확인응답(Acknowledgement) 지연
TCP 느린 시작(slow-start)
네이글(nagle) 알고리즘과 TCP_NODELAY
TIME_WAIT 지연과 포트 고갈
cf. TCP 흐름 제어 및 혼잡 제어 (+ 오류 제어)
흐름 제어(Flow control)
송신측과 수신측의 데이터 처리 속도 차이를 해결하기 위한 기법
Flow Control은 receiver가 packet을 지나치게 많이 받지 않도록 조절하는 것
기본 개념은 receiver가 sender에게 현재 자신의 상태를 feedback 한다는 점
해결방법
혼잡 제어(Congestion control)
송신측의 데이터 전달과 네트워크의 데이터 처리 속도 차이를 해결하기 위한 기법
해결방법
AIMD(Additive Increase / Multiplicative Decrease)
처음에 패킷을 하나씩 보내고 이것이 문제없이 도착하면 window 크기(단위 시간 내에 보내는 패킷의 수)를 1씩 증가시켜가며 전송하는 방법
패킷 전송에 실패하거나 일정 시간을 넘으면 패킷의 보내는 속도를 절반으로 줄인다.
Slow Start (느린 시작)
AIMD 방식이 네트워크의 수용량 주변에서는 효율적으로 작동하지만, 처음에 전송 속도를 올리는데 시간이 오래 걸리는 단점이 존재
Slow Start 방식은 AIMD와 마찬가지로 패킷을 하나씩 보내면서 시작하고, 패킷이 문제없이 도착하면 각각의 ACK 패킷마다 window size를 1씩 늘려준다. 즉, 한 주기가 지나면 window size가 2배로 됨
Fast Retransmit (빠른 재전송)
패킷을 받는 쪽에서 먼저 도착해야할 패킷이 도착하지 않고 다음 패킷이 도착한 경우에도 ACK 패킷을 보냄
중복된 순번의 패킷을 3개 받으면 재전송
(혼잡한 상황이 일어난 것이므로 혼잡을 감지, window size를 줄임)
Fast Recovery (빠른 회복)
혼잡한 상태가 되면 window size를 1로 줄이지 않고 반으로 줄이고 선형증가시키는 방법
HTTP 커넥션 관리
HTTP Connection 헤더
순차적인 트랜잭션 처리에 의한 지연
HTTP 커넥션 성능을 향상시킬 수 있는 4가지 기술
병렬 커넥션
보통 페이지를 더 빠르게 내려받을 수 있다.
하지만 항상 병렬 커넥션이 더 빠르지는 않다.
더 빠르게 로드하지 못 하더라도 사용자 경험 관점에서 빠르게 느껴질 수 있다.
병령 커넥션은 여러 객체가 있는 페이지를 빠르게 전송하지만 단점이 존재한다.
지속 커넥션
Keep-Alive
keep-alive: TCP 커넥션을 종료된 이후에도 얼마나 유지하고 있을 것 인가?
keep-alive header는 선택 사항이지만
Connection: Keep-Alive
헤더가 있을 때만 사용할 수 있다.단, 무조건 좋은 기능은 아니다.
멍청한(dumb) 프락시 문제
클라이언트는 keep-alive 헤더를 전송했지만 프락시 서버가 keep-alive 헤더를 단순 확장 헤더로 취급하는 경우에 문제가 발생한다.
원래 Connection 헤더는 hop-by-hop header이기 때문에 전송하면 안되지만 프락시 서버는 keep-alive가 무엇인지 모르기 때문에 서버에 그대로 전달하게 된다.
프락시 서버와 서버 사이에서는 서버는 커넥션을 끊지 않고, 유지하려고 하기 때문에 대기하게 되고, 프락시 서버는 커넥션이 끊어지기를 기다리게 된다.
클라이언트와 프락시 서버 간에는 서버와의 커넥션이 끊어지는 것을 기다리고 있기 때문에 keep-alive 커넥션을 통해 오는 클라이언트의 추가적인 요청을 처리하지 않게 된다.
HTTP/1.1의 지속 커넥션
Connection: close
를 보내도록 한다.지속 커넥션의 제한과 규칙
Connection: close
를 포함하면, 이후에는 추가적인 요청을 보낼 수 없다.파이프라인 커넥션
커넥션 종료
1. 마음대로 커넥션 끊기
2. Content-Length와 Truncation
3. 커넥션 끊기의 허용, 재시도, 멱등성
4. 우아한 커넥션 끊기
전체 끊기와 절반 끊기
close()
: 입력 채널과 출력 채널의 커넥션을 모두 끊는다. -> 전체 끊기shutdown()
: 입력 채널과 출력 채널 중 하나를 개별적으로 끊는다. -> 절반 끊기TCP 끊기와 리셋 에러
connection reset by peer
메시지를 보낸다.우아하게 커넥션 끊기
The text was updated successfully, but these errors were encountered: