250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- AVL트리
- HTTP
- JVM
- 점근적 표기법
- 백준장학금
- 멀티프로세서
- 백준 장학금
- 운영체제
- 자료구조
- spring
- 스케줄링
- 강화학습
- SpringSecurity
- 이분탐색이란
- 힙트리
- Kruskal
- 알고리즘
- 최소힙
- python
- heapq
- 연결리스트 종류
- JPA
- 완전이진트리
- posix
- 엔티티 그래프
- 프로세스
- 최대 힙
- MSA
- jpa n+1 문제
- 연결리스트
Archives
- Today
- Total
KKanging
[http 완벽 가이드] 4장 커넥션 관리 본문

이 내용은 http 완변 가이드란 책을 읽고 정리한 내용입니다.
더 자세한 내용이 궁금하시면 책을 직접 읽어보시는 걸 추천합니다.
4장 커넥션 관리
1. TCP 커넥션
- HTTP 통신은 TCP/IP 통신을 통해 데이터를 전송한다.
- 순서
- 브라우저가 호스트명을 추출한다.
- 브라우저가 포트 번호를 얻는다.
- 브라우저가 IP주소와 포트로 TCP 커넥션을 생성한다.
- 브라우저가 서버로 HTTP GET 요청 메시지를 보낸다.
- 브라우저가 서버에서 온 HTTP 응답 메시지를 읽는다.
- 브라우저가 커넥션을 끊는다
1.1 신뢰할 수 있는 데이터 전송 통로인 TCP
- TCP 커넥션은 인터넷을 안정적으로 연결해준다.
- 클라이언트에서 데이터를 전송하면 한쪽에 있는 바이트들은 반대쪽으로 순서에 맞게 전달된다.
1.2 TCP스트림은 세그먼트로 나뉘어 IP 패킷을 통해 전송된다.
- TCP는 IP 패킷이라고 불리는 작은 조각을 통해 데이터를 전송한다.
- HTTP가 메시지를 전송하고자 할 경우 연결되어있는 TCP 커넥션을 통해 데이터를 전송한다.
- TCP 세그 먼트라는 단위로 데이터 스트림을 잘게 나누고
- 세그 먼트를 IP 패킷이라고 불리는 봉투에 담아서 인터넷을 통해 데이터를 전달한다.
- TCP 세그먼트는 하나의 IP 주소에서 다른 IP 주소로 IP 패킷에 담겨 전달 된다.
1.3 TCP 커넥션 유지하기
- TCP 커넥션을 여러개 가질 수 있다.
- IP는 컴퓨터에 연결 포트 번호는 애플리케이션에 연결된다.
- TCP 커넥션은 네 가지 값으로 식별한다.
<발신지 IP 주소, 발신지 포트 , 수신지 IP 주소 ,수신지 포트>
- 두개의 다른 커넥션은 4가지 식별값의 일부는 같을 수 있으나
- 모두 같을 순 없다.
1.4 TCP 소켓 프로그래밍
- TCP 프로그래밍을 위해 소켓 API 가 있다.
- 소켓 API는 TCP커넥션의 생성 연결 입출력 닫기 같은 메서드를 지원한다.
2. TCP 의 성능에 대한 고려
- HTTP 바로 아래 계층이 TCP 계층이기 때문에 TCP의 성능에 영향을 많이 받는다.
2.1 HTTP 트랜잭션 지연
- TCP 커넥션을 연결하는 시간이 트랜잭션이 수행되는 시간보다 많은 시간을 차지하는걸 볼 수 있음
- HTTP 트랜잭션 시간 소요 부분
- 만약 URI에 기술되어있는 호스트에 최근 방문한적 없으면 DNS로 호스트명을 찾는데 시간이 걸림
- TCP 커넥션 요청을 서버에게 보내고 서버가 커넥션 허가 응답을 회신하기를 기다린다.
- 커넥션이 맺어지면 클라이언트는 요청을 보낸다. 그 요청을 서버에서 처리하는데 시간이 걸리는다.
- 서버가 응답을 보내는 것 역시 시간이 걸린다.
2.2 성능 관련 중요 요소
- TCP관련 지연들
- TCP 커넥션의 핸드셰이크 설정
- 인터넷의 혼잡을 제어하기 위한 TCP의 느린 시작
- 데이터를 한데 모아 한 번에 전송하기 위한 네이글 알고리즘
- TCP 의 편승 확인응답을 위한 확인응답 지연 알고리즘
- TIME_WAIT 지연과 포트 고갈
2.3 TCP 커넥션의 핸드셰이크 지연
- TCP 커넥션을 맺기 위한 조건을 갖추기 위해 연속으로 IP패킷 교환을 한다.
- 이런 패킷 교환은 HTTP 성능을 크게 저하 시킬 수 있다.
- 다음은 TCP 커넥션이 핸드 셰이크를 하는 순서이다.
- 아주 큰 데이터를 주고 받는 경우가 아니라면 이 작은 데이터로 하는 커넥션 핸드 셰이크는 큰 지연을 유발한다.
2.4 확인응답 지연
- 수신자는 세그먼트를 온전히 받으면 확인 응답 패킷을 송신자에게 반환한다.
- 만약 송신자가 특정 시간내에 확인응답 메시지를 받지 못하면 패킷이 파기 되었거나 오류가 있는걸로 판단하여 다시 데이터를 전송한다.
- 확인 응답은 데이터의 크기가 작기 때문에 TCP는 같은 방향으로 송출되는 데이터 패킷에 확인 응답을 같이 편승 시킨다(PIGGYBACK) →이는 효율적이다.
- 좀 더 편승을 높이기 위해 확인 응답 지연 알고리즘을 이용한다.
- → 확인 응답을 바로 보내지 않고 버퍼에 0.1~0.2초 동안 보관하여 같이 보낼 메시지를 찾는다. 못찾으면 따로 보낸다.
- 하지만 이는 요청과 응답만 있는 HTTP 통신에서는 편승의 기회가 잘 없기에 확인 응답 지연은 성능에 악영향을 끼친다.
- 확인 응답 지연은 비활성화가 가능하다.
2.5 TCP의 느린 시작으로 인한 지연
- TCP의 데이터 전송 속도는 TCP 커넥션이 만들어진 지 얼마나 지났는지에 따라 달라질 수 있다.
- TCP 커넥션은 시간이 지날 수록 튜닝된다.
- 처음에는 커넥션의 최대 속도를 제한하고 데이터가 성공적으로 전송됨에 따라서 속도 제한을 높여나간다. → 이런 느린 시작을 TCP 느린 시작이라고 부른다.
- 이는 새로 연결하는 TCP는 이미 튜닝된 커넥션보다 느리다는 점이 있다. 아래에서 지속 커넥션에 대해 배운다.
2.6 네이글(Nagle) 알고리즘으로 인한 지연
- TCP 세그먼트는 40바이트 상당의 플래그와 헤더를 포함하여 전송하기 때문에, 아주 작은 크기의 데이터를 전송하면 성능이 떨어진다.
- → 이를 해결한게 네이글 알고리즘이다.
- 네이글 알고리즘은 세그먼트가 최대 크기가 되지 않으면 보내지 않고 버퍼에 넣는다.
- 그리고 다른 패킷이 모두 확인 응답을 받거나, 충분한 크기가 되면 보낸다.
- 이는 성능 관련 큰 문제를 낳는다.
- 작은 크기의 메시지는 언제 채워질 지 모르기에 하염없이 기다려야한다.
- 확인 응답 지연 알고리즘과 같이 쓰이면 엄청 비효율적이다.
- → 확인 응답이 다 오면 보내지는데 확인 응답은 또 몇초 딜레이를 가지기 때문이다.
- 네이글 알고리즘 또한 비활성화가 가능하다.
- → 비활성화 시 작은 크기의 패킷이 너무 생기지 않도록 조심해야한다.
2.7 TIME_WAIT의 누적과 포트 고갈
- 이는 실제 성능에는 문제가 되지 않지만 측정시 문제가 되므로 측정하는 사람의 혼란을 줄 수 있다.
- TCP 커넥션을 끊으면, 종단에서는 커넥션의 IP 주소와 포트 번호를 메모리의 작은 제어영역(control block)에 기록해둔다. (커넥션 종료 지연)
- 이 정보는 같은 주소와 포트 번호를 사용하는 새로운 TCP 커넥션이 일정 시간 동안 생성되지 않게 하기 위한 것으로, 이 시간을
TIME_WAIT
라고 한다.
(보통 세그먼트의 최대 생명주기의 두 배 정도로 설정되며 2분 정도 : 2MSL)
TIME_WAIT 사용 이유 1
: 지연 패킷이 새로운 커넥션에 끼어드는 것을 막을 수 있다
TIME_WAIT을 사용하면 이전 커넥션의 지연 패킷이 새로운 커넥션에 삽입되는 문제를 방지할 수 있다.
매우 드문 경우이긴 하지만, SEQ=3의 패킷이 지연된 후 새로운 커넥션이 생성되었고, 때마침 해당 커넥션에 SEQ=3이 들어올 타이밍이었다면 데이터 무결성 문제가 발생할 수 있다.
TIME_WAIT 사용 이유 2
: LAST_ACK가 유실된 경우를 막을 수 있다
위 사진처럼 마지막 ACK가 유실된 경우, 상대는 LAST_ACK 상태에 빠지고, 새로운 커넥션이 SYN 패킷 전달시 RST를 리턴한다.
따라서 반드시 TIME_WAIT이 일정 시간 남아있어서 패킷의 오동작을 막아야 한다.
- 이런 커넥션 종료 지연은 평상시에는 큰 문제가 되지 않지만, 부하 테스트 상황에서는 문제가 될 수도 있어서 주의가 필요하다.
3. HTTP 커넥션 관리
- 이 장은 커넥션의 생성과 최적화에 관한 내용이다.
3.1 흔히 잘못 이해하는 Connection 헤더
- 클라이언트와 서버 사이에 HTTP는 프락시 서버 , 캐시 서버 등과 같은 중개 서버가 놓이는 것을 허락한다.
- 어떤 경우에는 두 개의 인접한 HTTP 애플리캐이션이 현재 맺고 있는 커넥션에만 적용될 옵션을 지정해야 할 때가 있다.
- HTTP 커넥션 헤더 필드는 커넥션 토큰을 쉼표로 구분하여 가지고 있다. 그 값들은 다른 커넥션에 전달되지 않는다.
- connection 토큰 값은 아래 3가지 종류로 올 수 있다.
HTTP 헤더 필드 명 (홉별 헤더 명)
: 여기 적힌 헤더들은 모두 다른 곳으로 전달하는 시점에는 삭제되어야 한다예외적으로 여기에 적혀 있지 않아도 홉별(hop-by-hop) 헤더인 것들도 있다 : Proxy-Authenticate, Proxy-Connection, Transfer-Encoding, Upgrade임시적인 토큰 값
: 커넥션에 대한 비표준 옵션을 의미close 값
: 이 트랜잭션이 끝나면 커넥션이 종료되어야 함을 의미
- 홉별(hop-by-hop): 홉은 각 서버를 의미 , 홉별은 특정 두 서버 간에만 영향을 미치고 다른 서버 간에는 영향을 미치지 않음을 뜻한다.
-
- HTTP 헤더명에 적힌 헤더는 다른 커넥션에 전달 되면 안된다.
3.2 순차적인 트랜잭션 처리에 의한 지연
- 순차적인 트랜잭션을 처리한다고 가정하고 이미지 4개를 요청한다고 가정해보자
- TCP 커넥션1을 맺고 리소스를 트랜잭션1 커넥션2을 맺고 트랜잭션 2…
- 물리적인 지연 뿐 아니라 사용자는 이미지가 하나씩 로드 되므로 심리적인 지연도 크다.
- 이를 해결할 기술 4가지가 있다.
- 병렬(parallel) 커넥션
- 지속(persistent) 커넥션
- 파이프라인(pipelined) 커넥션
- 다중(multiplexed) 커넥션
4. 병렬 커넥션
- 위 순차처리는 4가지 이미지를 로드하는데 한개의 트랜잭션이 끝날 때까지 대기해야 했다.
- 병렬 커넥션은 4개의 커넥션을 거의 동시에 연결하여(약간의 지연만 발생) 트랜잭션을 병렬 처리할 수 있다.
병렬 커넥션이 항상 더 빠르지는 않다.
- 클라이언트의 대역폭이 좁을 때에는 대부분에 시간을 데이터를 전송하는 데만 쓸 것이다.
- 여러 개의 객체를 병렬로 내려받는 경우, 이 제한된 대역폭 내에서 각 객체를 전송 받는것은 느리기 때문에 성능상의 장점은 거의 없어진다.
- 병렬 커넥션이 빠르다고 많이 연결하게 되면 서버에 부하가 크다.
- 그래서 브라우저는 병렬 커넥션 수를 제한한다.
- 그리고 서버는 과도한 커넥션이 연결되면 그것을 끊어버릴 수도 있다.
5. 지속 커넥션
- 보통 클라이언트는 같은 사이트에 여러 개의 커넥션을 맺는다.
- 예를 들어 이미지 같은 웹사이트도 있고, 상당 수의 하이퍼링크가 같은 사이트를 가리킨다.(사이트 지역성 site locality)라고 부름
- 이때 웹페이지를 가지고 온다고 서버와 커넥션을 맺고 이미지를 가지고 온다고 커넥션을 맺으면
- TCP 커넥션의 지연 때문에 성능에 엄청 비효율적이다.
- 한번 맺은 커넥션을 재사용 함으로써 TCP의 느린 시작을 피할 수 있다. 이를 지속 커넥션이라 부른다.
5.1 지속 커넥션 VS 병렬 커넥션
- 병렬 커넥션은 순차 커넥션 보다 빠르다는 장점이 있지만 TCP의 느린 시작 그리고 실제로 연결할 수 있는 병렬 커넥션의 수에는 제한이 있다는 점이란 단점들이 존재한다.
- 이에 반해 지속 커넥션에 장점이 있다.
- TCP커넥션에 느린시작을 없에줌
- 튜닝된 커넥션을 유지
- 커넥션 수를 줄여줌
- 하지만 이를 관리하지 못할 경우 수많은 계속 연결 상태로 있는 커넥션이 쌓일 것이다.
- 이는 서버나 클라이언트에 불필요한 소모를 발생한다.
- 지속 커넥션은 병렬 커넥션과 같이 사용할 때 효과적이다.
- 많은 수의 애플리케이션은 적은 수의 병렬 커넥션만을 맺고 그것을 유지한다.
- 두가지 지속 커넥션 타입이 있는데
- HTTP/1.0+에 keep-alive 커넥션이 있고
- HTTP/1.1 에는 지속 커넥션이 있다.
5.2,3,4 HTTP/1.0+ 의 Keep-Alive 커넥션 동작과 옵션
- Keep-Alive은 HTTP 1.1 명세에는 빠졌지만 아직 HTTP/1.0+를 사용하는 애플리캐이션이 많기 때문에 이를 처리할 수 있어야한다.
Connection: Keep-Alive
- 위 헤더가 있는 요청을 클라이언트가 보내면 클라이언트가 이 트랜잭션이 끝나도 커넥션을 유지하기를 원한다는 의미이다.
- 응답에 위 헤더를 포함시켜야 클라이언트는 이 커넥션이 지속되는지 알 수 있다.
- 만약 포함시키지 않을 경우 클라이언트는 커넥션이 서버가 끊을 것이라고 추정한다.
- Keep-Alive 헤더는 커넥션을 유지하기 바라는 요청일 뿐이다. 클라이언트나 서버가 이를 받았다고 해서 무조건 그것을 따를 필요는 없다.
- 언제든지 Keep-Alive 헤더를 끊을 수도 제한할 수도 있다.
- timeout 파라미터: 커넥션이 얼마간 유지될건지.
- max 파라미터: 커넥션이 몇 개의 HTTP 트랜잭션을 처리할 때까지 유지될 건지.
- 하지만 이대로 동작할지는 보장하지 않는다.
- 디버깅을 주목적으로 하는 임의의 속성. 이름=값 형식
5.5 Keep-Alive 커넥션 제한과 규칙
- Keep-Alive sms HTTP/1.0에서 기본으로 사용되지는 않는다. → Keep-Alive 커넥션을 맺고자한다면 Connection : Keep-Alive 헤더를 포함하고 보내야한다.
- 클라이언트는 Connection : Keep-Alive 헤더가 없는 것을 보고 요청 처리 후 커넥션을 끊을거라 예상한다.
- 커넥션이 끊어지기 전 엔터티 본문에 길이나 타입을 정확하게 알아야 커넥션을 유지할 수 있다.
- 이는 앤터티에 본문에 대한 인코딩이 잘되어야한다. 트랜잭션이 끝나는 시점에 기존 메시지의 끝과 새로운 메시지의 시작을 정확히 알 수 없기 때문
- 프록시와 게이트웨이는 메시지를 전달하거나 캐시에 넣기 전에 Connection 헤더에 명시된 모든 헤더 필드와 Connection 헤더를 제거해야 한다.
- keep-alive 커넥션은 Connection 헤더를 인식하지 못하는 프록시 서버와는 맺어지면 안된다(Dumb Proxy로 인해 헤더가 다음 홉으로 넘어가기 떄문에. 그러나 그런 경우가 많이 발생한다)
- HTTP/1.0을 따르는 기기로부터 받은 모든 Connection 헤더 필드는 무시해야한다.
- 클라이언트는 응답 전체를 모두 받기 전에 커넥션이 끊어진 경우, 요청을 다시 보낼 수 있게 준비되어 있어야 한다.
5.6 Keep-Alive와 멍청한 프록시 문제
- 멍청한 프록시는 connetion헤더를 인식하지 못하고 그냥 메시지를 보낸다.
- 이에 클라이언트와 서버는 keep-alive로 인식하여 커넥션이 유지될것이라 믿는다.
- 하지만 프록시는 연결이 끝날때까지 대기할 것이고, 클라이언트가 지속될거라고 믿는 커넥션에 요청을 보내면 프록시는 대기중이라 이를 해결하지 않는 문제가 발생한다.
5.7 Proxy-Connection 살펴보기
- 모든 웹 애플리케이션이 HTTP 최신 버전을 지원하지 않아도 멍청한 프록시 문제를 해결할 수 있는 차선책으로 제시된 게 Proxy-Connection 헤더이다.
- 이걸 이용하면, 멍청한 프록시가 Proxy-Connection 헤더를 전달하더라도, 웹 서버는 이걸 무시하기 때문에 별문제가 되지 않는다.
- 영리한 프록시(지속 커넥션을 이해하는)라면, 의미 없는 Proxy-Connection 헤더를 Connection 헤더로 바꿈으로써 원하던 효과를 얻을 수 있다.
- 이 방식은 서버와 클라이언트 사이에 프록시가 단 한개 존재하는 경우에만 동작한다.
- 프록시가 2개 이상이고, 그 사이에 멍청한 프록시가 섞여있는경우 영리한 프록시가 이를 connection 헤더로 변환하면 똑같이 문제가 발생한다.
5.8 HTTP/1.1의 지속 커넥션
- HTTP/1.1은 keep-alive 커넥션을 지원하지 않는 대신, 설계가 개선된 지속 커넥션을 지원한다.
- 더 잘 동작한다.
- keep-alive 커넥션과 지속 커넥션은 기본으로 활성화 되어있다.
- 커넥션을 끊기를 원한다면 connection:close를 명시해야한다.
- connection:close이 없으면 응답 후에도 커넥션이 계속 유지되는것으로 간주한다.
- 하지만 이는 언제든지 클라이언트나 서버에서 끊을 수 있으며 connection:close가 상태를 항상 나타내지는 않는다.
5.9 지속 커넥션의 제한과 규칙
- keep-alive와 마찬가지로 엔티티 본문은 정확한 Content-Length를 가지거나 청크 전송 인코딩되어 있어야 한다.
- HTTP/1.1 프록시는 클라이언트와 서버 각각에 대해 별도의 지속 커넥션을 맺고 관리해야 한다.
- 단, 프록시 서버는 클라이언트의 커넥션 관련 지원 범위를 알고 있지 않은 한 지속 커넥션을 맺으면 안된다
- 오래된 프록시가 Conenction 헤더를 전달하는 문제가 생길 수 있기 때문에
- HTTP/1.1 애플리케이션은 중간에 끊어지는 커넥션을 복구할 수 있어야 한다. 클라이언트는 다시 보내도 문제가 없는 요청이라면 가능한 한 다시 보내야 한다.
- 하나의 사용자 클라이언트는 서버의 과부하를 방지하기 위해서 , 넉넉잡아 두 개의 지속 커넥션을 유지해야 한다.
6 파이프라인 커넥션
- 여러 개의 요청은 응답이 도착하기 까지 Queue에 쌓인다.
- 이는 첫번째 요청을 보내면서 2번째 3번째 요청을 보낼 수 있다. 이는 왕복시간을 줄여서 시간을 단축시켜준다.
- HTTP/1.1은 지속 커넥션을 통해 요청을 파이프라이닝 할 수 있다. (하나의 TCP 커넥션을 통한 병렬 HTTP 요청이 가능)
그러나 파이프라인에는 여러가지 제약사항이 있다.
- HTTP 클라이언트는 커넥션이 지속 커넥션인지 확인하기 전까지는 파이프라인을 이어서는 안된다.
- HTTP 응답은 요청 순서와 같게 와야 한다. 이걸 순서에 맞게 정렬시킬 방법은 없다.
- HTTP 클라이언트는 언제 연결이 끊어지더라도 완료되지 않은 요청이 파이프라인에 있으면 언제든 다시 요청을 보낼 준비가 되어 있어야 한다.
- POST 요청과 같이 반복해서 보낼 경우 문제가 생기는 요청(비멱등한 요청)은 파이프라인을 통해 보내면 안된다.
- 에러가 발생하면 파이프라인을 통한 요청 중 어떤 것이 서버에서 처리되었는지 클라이언트는 알 수 없고, POST 같은 비멱등 요청을 재차 보내면 문제가 생길 수 있기 때문이다.
7 커넥션 끊기에 대한 미스터리
- 커넥션 관리(특히 언제 어떻게 커넥션을 끊는가)에는 명확한 기준이 없다.
- 이 이슈는 수많은 개발자가 알고 있는 것보다 더 미묘하며, 그에 관한 기술 문서도 별로 없다.
7.1 마음대로' 커넥션 끊기
- HTTP 클라이언트, 서버, 혹은 프락시는 언제든지 TCP 전송 커넥션을 끊을 수 있다.
- 보통 커넥션은 메시지를 다 보낸 다음 끊지만, 에러가 있는 상황에서는 헤더의 중간이나 다른 엉뚱한 곳에서 끊길 수 있다.
- 지속 커넥션이 일정 시간 동안 요청을 전송하지 않고 유휴 상태에 있으면 서버는 그 커넥션을 끊을 수 있다.
- 하지만 서버가 유휴 상태에 있는 커넥션을 끊는 시점에, 서버는 클라이언트가 다시 요청하지 않을 것이라고 확신하지 못한다. 클라이언트가 다음 요청을 보낸다면 문제가 생긴다.
7.2 Content-Length와 Truncation
- 각 HTTP 응답은 본문의 정확한 크기 값을 가지는 Content-Length 헤더를 가지고 있어야 한다.
- 클라이언트나 프락시가 커넥션이 끊어졌다는 HTTP 응답을 받은 후, 실제 전달 된 엔터티 본문의 길이와 Content-Length가 일치하지 않거나 Content-Length 헤더가 존재하지 않는다면 수신자는 데이터의 정확한 길이를 서버에게 물어봐야 한다.
- 만약 수신자가 캐시 프락시일 경우 응답을 캐시하면 안되며, Content-Length를 정정하려 하지 말고 메시지를 받은 그대로 전달해야 한다.
7.3 커넥션 끊기의 허용, 재시도, 멱등성
- 커넥션은 에러가 없더라도 언제든 끊을 수 있다.
- HTTP 애플리케이션은 예상치 못하게 커넥션이 끊어졌을 경우를 대응할 수 있도록 준비해야 한다.
- 클라이언트는 트랜잭션 수행 중 커넥션이 끊어졌을 때 다시 트랜잭션을 전송해도 문제가 없다면 커넥션은 다시 맺고 한번 더 전송해야 한다.
- GET 요청은 반복적으로 요청하더라도 결과적으로 아무런 영향을 끼치지 않지만, 온라인 서점에서 주문을 하는 POST 요청은 반복할 경우 여러 번 주문이 될 것이기 때문에 반복은 피해야 한다.
- 한 번 혹은 여러 번 실행해도 같은 결과를 반환한다면 그 트랜잭션은 멱등(idempotent)하다고 한다.
- GET, HEAD, PUT, DELETE, TRACE, OPTIONS 메서드들은 멱등
- POST와 같은 비멱등 메서드는 파이프라인을 통해 요청하면 안된다.
- 비멱등 요청을 다시 보내야 한다면, 이전 요청에 대한 응답을 받을 때까지 기다려야 한다.
- 비멱등 메서드나 순서에 대해 에이전트가 요청을 다시 보낼 수 있도록 기능을 제공할 때 자동으로 재시도하면 안된다. 캐시된 POST 요청 페이지를 다시 로드하려고 할 때, 요청을 다시 보내기를 원하는지 묻는 대화상자를 보여준다.
7.4 우아한 커넥션 끊기
- TCP 커넥션은 양방향이며 양쪽에는 데이터를 읽거나 쓰기 위한 입력 큐와 출력 큐가 있다. 한쪽 출력 큐에 있는 데이터는 다른 쪽의 입력 큐에 보내질 것이다.
전체 끊기와 절반 끊기
- 애플리케이션은 TCP 입력 채널과 출력 채널 중 한 개만 끊거나 둘 다 끊을 수 있다.
- close()를 호출하면 TCP 커넥션의 입력 채널과 출력 채널의 커넥션을 모두 끊는다.
- shutdown()을 호출하면 입력 채널이나 출력 채널 중 하나를 개별적으로 끊을 수 있다.
TCP 끊기와 리셋 에러
- 단순한 HTTP 애플리케이션은 전체 끊기만을 사용할 수 있다.
- 하지만 애플리케이션은 다른 애플리케이션들과 통신할 때, 그리고 그들과 파이프라인 지속 커넥션을 사용할 때, 기기들에 예상치 못한 쓰기 에러를 발생하는 것을 예방하기 위해 '절반 끊기'를 사용해야 한다.
- 보통은 커넥션의 출력 채널을 끊는 것이 안전하다.
- 클라이언트에서 이미 끊긴 입력 채널에 데이터를 전송하면, 서버의 운영체제는 TCP 'connection reset by peer' 메시지를 클라이언트에게 보낸다.
- 대부분 운영체제는 이것을 심각한 에러로 취급하여 버퍼에 저장된, 아직 읽히지 않은 데이터를 모두 삭제한다.
우아하게 커넥션 끊기
- 우아한 커넥션 끊기를 구현하는 것은 애플리케이션 자신의 출력 채널을 먼저 끊고 다른 쪽에 있는 기기의 출력 채널을 끊기는 것을 기다리는 것이다.
'cs > http' 카테고리의 다른 글
[http 완벽 가이드] 6장 프락시 (0) | 2023.08.13 |
---|---|
[http 완벽 가이드] 5장 웹 서버 (0) | 2023.08.06 |
[http 완벽 가이드] 3장 HTTP 메시지 (0) | 2023.07.28 |
[http 완벽 가이드] 2장 URL과 리소스 (0) | 2023.07.28 |
[http 완벽 가이드] 1장 HTTP 개관 (0) | 2023.07.28 |