HTTP 완벽가이드 4장 커넥션 관리

어겐어갠·2022년 5월 24일
0

4장 커넥션 관리

http 커넥션과 메세지의 흐름

4.1 TCP 커넥션

http 통신읜 TCP/IP로 커넥션을 맺고 이루어진다.
커넥션이 맺어지면 메세지들은 안전하게(손실, 손상 없이) 전달된다.

4.1.1 신뢰할 수 있는 데이터 전송 통로 TCP

TCP는 http에게 신뢰할 만한 통신 방식을 제공하고 그로 인해 바이트들은 순서에 맞게 정확히 전달된다.

TCP는 세그먼트 단위로 데이터 스트림을 잘게 나누고, IP 패킷이에 담아 데이터를 전달한다.

4.1.3 TCP 터넥션 유지하기

컴퓨터는 TCP 커넥션을 여러개 가지고있고, 포트 번호를 통해 다수개의 커넥션을 유지한다.
발신지 IP주소 , 발신지 포트, 수신지 IP주소, 수신지 포트
네가지 값으로 식별한다.
이 네가지 값이 모두 동일한 커넥션은 존재할 수 없다.

4.2 TCP의 성능에 대한 고려

http 트랜잭션의 성능은 TCP 성능에 영향을 받는다.( 계층이 바로 위 아래로 존재하기 때문)

4.2.1 http 트랜잭션 지연

트랜잭션에서 커넥션 연결, 요청전송, 응답 메세지를 보내는 시간에 비해 실제 처리시간은 매우 짧다.
즉, 대부분의 http지연은 TCP 네트워크 통신에서 발생한 지연이다.
현재는 이러한 TCP지연(IP주소를 찾거나 커넥션 연결을 위한 요청, 응답)이 많이 해결되었다.

4.2.3 TCP 커넥션 핸드셰이크 지연

50% 이상의 지연을 차지한다.
클라이언트와 서버는 커넥션을 생성하기위해 SYN, ACK로 핸드셰이크를 하는데 여기서 지연이 발생한다.

4.2.4 확인응답 지연

성공적인 데이터 전송을 보장하기 위해 TCP는 확인 체계를 가지는데 세그먼트를 온전하게 받는데 성공하면 확인 응답 패킷을 보낸다.
확인 응답 패킷은 크기가 작아 효율적으로 활용하기 위해 같은 방향으로 송출되는 데이터 패킷에 편승시키는데,
만약 여기서 같은 방향으로 송출되는 데이터 패킷을 찾지 못하면 지연이 발생한다.

4.2.5 느린 시작

TCP 커넥션은 첫 생성시에는 속도 제한이 걸려있으며, 전송이 성공적으로 전달될경우 점점 더 튜닝되어 속도 제한이 높아진다.
이러한 문제를 해결하기 위해 이미 존재하는 커넥현을 재사용하는 "지속 커넥션"이 있다.

4.2.6 네이클 알고리즘, TCP_NODELAY

네이클 알고리즘 = 세그먼트가 최대 크기가 되기 전까지 전송을 지연하는 것.
만약 목표 패킷까지 채우지 못하면 지연이 심해진다.
확인 응답 지연과 함께 쓰이면 형편없이 동작한다.
TCP_NODELEAY를 쓰면 네이글 알고리즘을 비활성할 수 있다.

4.3.1 흔이 잘못 이해하는 Connection 헤더

클라이언트와 서버 사이에 여러 중개 서버가 있기 때문에 Connection 헤더를 잘 사용해야한다.
커넥션 헤더에는 홉-바이-홉 헤더명을 기술하여 헤더 '헤더 보호하기'를 한다.
다음 홉으로 메세지를 넘길때 커넥션 헤더와 커넥션 헤더에 기술된 모든 헤더들을 삭제한다.

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

한개의 페이지를 구성하는데 여러 트랜잭션이 필요하고, 이 트랜잭션들이 순차적으로 처리되며, 각각 새로운 커넥션을 구성한다면?
커넥션 발생시 지연과 느린시작 지연이 발생한다.
또한 모든 객체를 내려받기 전까지 텅 빈 화면만 나온다.

이를 해결하기 위한 방법들 4가지 = 병렬 커넥션, 지속 커넥션, 파이프라인 커넥션, 다중 커넥션

4.4 병렬 커넥션

병렬로 커넥션을 연결하여 각 트랜잭션이 독립적으로 실행되게 한다.

4.4.2 병력 커넥션이 항상 더 빠르지는 않다.

네트워크 대역폭이 좁을 경우 성능을 기대할 수 없다.
메모리를 많이 소모하며, 자체적인 성능 문제를 발생시킨다.
그래서 적은 수(4개) 의 병렬 커넥션을 사용한다.
다만 페이지의 변화가 조금씩 보이므로 체감 속도는 더 빠르게 느껴질 수 있다.

4.5 지속 커넥션

처리가 완료된 후에도 계속 연결된 상태로 있는 TCP 커넥션
재사용함으로써 효율성을 높인다.

4.5.1 지속 vs 병렬

지속 커넥션은 커넥션 연결시의 지연을 줄여주고, 튜닝된 커넥션을 계속 사용하며, 이로써 커넥션의 수를 줄여준다.
다만 잘못 사용할 경우 계속 연결된 커넥션이 쌓여 자원의 불필요한 소모를 야기한다.

그러므로 지속커넥션과 병렬 커넥션을 같이 사용할 때 가장 효과를 볼 수 있다.

4.5.3 Keep-Alive 동작

커넥션을 유지하기 위해 요청에 Connection:Keep-Alive 헤더를 포함시킨다.
Keep-Alive를 할 경우 커넥션이 계속 유지되어 지연을 줄인다.

다만, 이 요청은 요청일 뿐 거절당하고 커넥현이 끊길 수 있다.
Keep-Alive 헤더에는 여러 파라미터가 있다.

4.5.5 Keep-Alive 커넥션 제한과 규칙

p.107

4.5.6 Keep-Alive와 멍청한 프락시

Connection 헤더를 이해하지 못하고 그대로 다음 메세지에 Connection 헤더를 포함하는 프락시가 있다.(실제로는 삭제하고 Connection 헤더에 기술된 헤더들도 삭제해야 함)
이에 관련된 문제와 그 과정은 p.109

4.5.7 Proxy-Connection

위의 문제점을 해결하기 위한 차선책
멍청한 프락시는 Connection 헤더를 다음 메세지에 담아 전달하겠지만 웹 서버는 Proxy-Connection이 자신에게 필요한 헤더가 아님을 알고 무시할 수 있다.
하지만 멍청한 프락시 양 옆에 영리한 프락시가 있을경우 다시 문제가 발생한다.

4.5.8 HTTP/1.1 의 지속 ㅓ넥현

http 1.1 에서는 keep-alive 커넥션을 지원하지 않는다.
대신 더 개선된 지속 커넥션을 제공한다.
별도 설정이 없다면, 모든 커넥션을 지속 커넥션으로 취급한다.

4.5.9 지속 커넥션의 제한과 규칙

p.113

4.6 파이프라인 커넥션

http/1.1의 짓고 커넥션을 통해 요청을 파이프라이닝 할 수 있고 이는 keep-alive의 성능을 높인다.

이에 대한 제약사항으로는

  • http 클라이언트는 지속 커넥션인지 확인 전까지는 파이프라인을 이어서는 안되고
  • 응답은 요청 순서와 같아야하며
  • 완료되지 않은 요청이 있으면 언제든 다시 요청을 보낼 수 있어야하고
  • 멱등성이 보장되지 않을경우 파이프라인을 통해 보내면 안된다.

4.7.1 마음대로 커넥션 끟기

어떠한 http 클라이언트, 서버, 프락시는 언제든 전송 커넥션을 끊을 수 있다.
보통 커넥션은 메세지를 다 보낸 다음 끊지만, 에러가 있는 상황에서는 헤더의 중간이나 다른 곳에서 끊길 수 있다.
지속 커넥션이 일정 시간 동안 요청하지 않으면 서버는 그 커넥션을 끊을 수 있다.
하지만 서버가 유휴 상태의 커넥션을 끊을 때 서버는 클라이언트가 다시 요청하지 않을 것이라고 확신하지 못하기 때문에 그 이후 클라이언트는 요청을 하게 될 경우 문제가 생긴다.

4.7.2 Content-Length, Truncation

http 응답은 본문의 정확한 크기 값을 가지는 Content-Length 헤더를 가지고 있어야 한다.
커넥션이 끊긴 뒤에 실제 전달된 엔터티의 길이와 Content-Length의 값이 일치하지 않을경우 혹은 Content-Length가 존재하지 않으면,
서버에게 정확한 데이터의 길이를 물어봐야한다.

4.7.3 커넥션 끊기의 허용, 재시도, 멱등성

http 애플리케이션은 예상외의 커넥션 끊기에 대해 적절히 대응할 수 있어야한다.
즉, 예상치못하게 커넥션이 전송 중간에 끊긴다면 재전송이 가능해야한다.
하지만 POST와 같이 멱등하지 않을경우(요청에 대한 결과가 계속 달라질 경우) 재전송을 하면 안된다. (= 파이프라인을 통해 요청하면 안 된다.)

4.7.4 우아한 커넥션 끊기

  • 전체 끊기
    close() -> 입력 채널과 출력 채널의 커넥션을 모두 끊는다.

  • 절반 끊기
    shutdown() -> 입력 혹은 출력 둘중 하나 끊는다.

  • TCP 끊기와 리셋 에러
    단순한 http 애플리케이션은 전체 끊기만 할 수 있다.
    하지만 애플리케이션이 각기 다른 http 클라이언트와 파이프라인 지속 커넥션을 사용할 때, 예상 외의 쓰기 에러를 예방하기 위해 '절반 끊기'를 사용한다.
    보통은 ㅊㄹ력 채널의 커넥션을 끊는 것이 안전하다.

  • 우아하게 커넥션 끊기
    애플리케이션이 자신의 출력 채널을 먼저 끊고 다른 쪽 기기의 출력 채널이 끊기는 것을 기다리는 것.

profile
음그래

0개의 댓글