티스토리 뷰

728x90
반응형

tcp는 세그먼트 단위로 데이터스트림을 나누고 ip패킷이라는 봉투에 담아서 데이터를 보낸다

 

ip패킷은 ip패킷 헤더, tcp 세그먼트, tcp 데이터조각

 

tcp 세그먼트 : 데이터 스트림 덩어리를 운반하고

ip 패킷 : tcp 세그먼트를 운반

 

컴퓨터는 항상 여러개의 tcp 커넥션을 가지고있다

 

ip주소는 서버주소 포트번호는 어플리케이션 주소

 

tcp 커넥션은 다음의 4가지를 가지고있따

 

발신자 ip주소, 발신지 포트번호,수신자 ip주소 수신지 포트번호

 

서로 다른 tcp커넥션이 위 4가지가 모두 같을수없다 (일부는 같을수있다)

 

소켓 API 호출                                 설명

s = socket( (param eters))         연결이 되지 않은 익명의 새로운 소켓 생성

bind(s, (local IPport>)         소켓에 로컬 포트 번호와 인터페이스 할당

connects(s, <remote IPport>)         로컬의 소켓과 원격의 호스트 및 포트 사이에 TCP 커넥션 생성

listen(s,..) 커넥션을 받아들이기 위해 로컬 소켓에 허용함을 표시

s2 = accept(s) 누군가 로컬 포트에 커넥션을 맺기를 기다림

n = read(s, buffer, n) 소켓으로부터 버퍼에 n바이트 읽기 시도

n = write(s,buffer,n) 소켓으로부터 버퍼에 n바이트 쓰기 시도

close(s) TCP 커넥션을 완전히 끊음

shutdown(s, <side >) TCP 커넥션의 입출력만 닫음

getsockopt(s, . . . ) 내부 소켓 설정 옵션값을 읽음

setsockopt(s, . . . ) 내부 소켓 설정 옵션값을 변경

 







클라이언트나 서버가 너

무 많은 데이터를 내 려받거나 복잡하고 동적 인 자원들을 실행하지 않는 한, 대부분

HTTP 지 연은 TCP 네트워크 지연 때문에 발생

 

http 지연요소

 

1. DNS에서 서버 IP를찾는시간

2. 커넥션을 서버에서 받아주는데 걸리는시간

3. 서버가 요청메세지를 처리하는시간

4. 서버가 응답을 보내는시간

 

 

성능관련 중요요소

 TCP 커 넥션의 핸드세 이크 설정

인터넷의 혼잡을 제어하기 위한 TCP의 느린 시작(slowstart)

데이터를 한데 모아 한 번에 전송하기 위한 네이글(nagle) 알고리즘

. TCP의 편승(piggyback) 확인웅답(acknowledgment)을 위한 확인응답 지 연 알고

리즘

• TIME_WAIT 지 연과 포트 고갈

 

 

tcp 핸드셰이크

tcp연결하기위해서 ip패킷을 여러번 교환한다

작은 크기의 데이터 전송에 커넥션이 사용된다면 이런 패킷 교환은 HTTP 성능을 크게 저

하시킬 수 있다.

 

 

핸드셰이크 과정

 

1. 서버에게 작은 tcp패킷을 보낸다 SYN라는 특별한 플래그가있는데 커넥션 연결요청이다

2. 서버가 요청을받으면 잘받았다는 확인응답(ACK)을 보낸다

3. 클라이언트가 확인응답을 받으면 연결이되었다는 의미로 ACK를 또 보내고 거기에 데이터를 실어서 보낸다.

 

 

HTTP 트랜잭션이 아주 큰 데이터를 주고받지 않는 평범한 경우에는,S Y N /

SYN+ACK 핸드셰이크가 눈에 띄는 지연을 발생시킨다

 

 

TCP ACK 패킷은 HTTP 요청 메시지 전체를 전달할 수 있을 만큼 큰

경우가 많고, 많은 HTTP 서버 응답 메시지는 하나의 IP 패킷에도 담길 수 있다

 

크기가 작은 HTTP 트랜잭션은 50% 이상의 시간을 TCP를 구성하는 데 쓴다

 

그렇기에 이 커넥션을 재활용해야한다

 

 

확인응답 지연

TCP는 성공적인 데이터 전송을

보장하기 위해서 자체적인 확인 체계를 가진다

 

 

 TCP 세그먼트는 순번과 데이터 무결성 체크섬을 가진다

 

각 세그먼트의 수신자는 세그먼트를 온전히 받으면 작은 확인응답 패킷을 송신자에게 반환한다

 

송신자가 특정 시간 안에 확인응답 메시지를 받지 못하면 패킷이 파기되었거나 오

류가 있는 것으로 판단하고 데 이터를 다시 전송한다

 

확인응답은 그 크기가 작기 때문에,TCP는 같은 방향으로 송출되는 데이터 패킷

에 확인응답을 편승(piggyback)시킨다

 

데이터와 확인응답을 같은방향으로 가는 데이터패킷에 묶음으로써 네트워크를 효율적으로 이용

 

확인응답패킷이 많이 데이터패킷에 실어 나르려면 확인응답지연 알고리즘을 구현

 

HTTP통신은 요청, 응답이 전부이기때문에 확인응답이 데이터패킷에 실어 같이나갈 기회를 감소시킨다

 

확인응답 지연기능을 비활성화 시킬수있지만

TCP 내부알고리즘은 잘못만들어진 어플리케이션으로부터 인터넷을 보호하도록 설계되어있기때문에 TCP 내부알고리즘이 피하려는문제가 어플리케이션으로부터 생기지않는다는 확신이있어야 할수있다

 

 

TCP 느린시작

TCP 커넥션은 연결시간이 지나갈수록 튜닝해나간다 처음 연결되었을때보다 시간이 지남에따라 속도 제한을 조금씩 풀어간다 급작스러운 부하와 혼잡을 막는데 사용

 

 TCP가 한 번에 전송할 수 있는 패킷의 수를 제한

패킷이 성공적으로 전달되는 각 시점에 송신자는 추가로 2개의 패킷을 더

전송할 수 있는 권한을 얻는다

 

 HTTP 트랜잭션에서 전송할 데이터의 양이 많으면

모든 패킷을 한 번에 전송할 수 없다

 

그 대신 한 개의 패킷만 전송하고 확인응답을

기다려야 한다. 확인응답을 받으면 2개의 패킷을 보낼 수 있으며,그 패킷 각각 대

한 확인응답을 받으면 총 4개의 패킷을 보낼 수 있게 된다. 이를혼잡 윈도를 연다

(opening the congestion window)’ 라고 한다

 

이 혼잡제어 기능 때문에,새로운 커넥션은 이미 어느 정도 데이터를 주고받은

튜닝된 커넥션보다 느리다. ‘튜닝된 커넥션은 더 빠르기 때문에,HTTP에는 이미

존재하는 커넥 션을 재사용하는 기능이 있다





네이글 알고리즘

tcp는 어떠한 크기의 데이터든 tcp스택에 전송될수있도록 도와주는 데이터스트림 인터페이스를 제공한다

하지만 데이터가 전송될때 tcp세그먼트는 40바이트 가량 플래그나 헤더를 포함하기때문에 작은 데이터패킷을 여러번 전송하는것은 네트워크 성능이 떨어진다

 

그래서 데이터를 적정량까지모아서 한덩어리로 전송하는 네이글 알고리즘이있다

데이터들이 모두 확인응답을 받을상태라면 적정량을 채우지못해도 전송할수있다

 

네이글 알고리즘의  문제

1. 작은 데이터들을 모아도 적정량에 도달하지못하면 언제 추가될지모르는 추가데이터를 기다려야한다

2. 확인응답지연과 같이사용하면 더 안좋아진다  데이터들이 확인응답을 기다리고있는데 확인응답 지연을 사용하면 100~ 200 밀리초 지연된다

 

그래서 TCP_NODELAY를 사용하여 네이글 알고리즘을 비활성화할수있다

 

비활성화를 한다면 큰 크기의 데이터를 만들어야한다

 

 

TIME_WAIT의 누적과 포트고갈

TIME_WAIT 포트고갈은 성능 측정시엔 심각한 문제를 발생하지만 그냥 사용할시에는 전혀 문제가되지않는다

tcp 커넥션의 종단지점에서 IP와 포트번호를 작은제어영역에기록해 둔다 그리고 TCP세그먼트 최대생명주기 시간의 2(2MSL) 동안 그값을 가지고있다 지나면 지운다        이 시간안에 새로운 커넥션이 이와같은 값으로 만들어지는것을 방지하기위해

 

2MSL시간을 줄이는것은 매우 조심해서해야한다

만약 이전 커넥션의 패킷이 그 커넥션과 같은 연결 값으로 생성된 커넥션에 삽입되면,패킷은 중복되고 TCP 데이터는 충돌할 것이다

 

2MSL의 커넥션 종료지연은 클라이언트로 서버에 계속 테스트를 하기위해 연결을끊고 다시 접속하고해야하는데 끊고 2MSL시간 동안 기다려야하고 그렇다고 포트를 바꾸자니 포트는 한정되어있으니 성능이 안좋아진다

 

 

각각 한 개의 클라이언트와 웹 서버가 있고,TCP 커넥션을 맺기 위한 네 개의 값

이 있다고 해보자.

<발신지 IP 주소, 발신지포트, 목적지 IP 주소, 목적지포트>

이 중에서 세 개는 고정 되어 있고 발신지 포트만 변경할 수 있다.

<클라이언트 IP, 발신지포트, 서버 IP, 80>

 

 

 

클라이언트가 서버에 접속할 때마다,유일한 커넥션을 생성하기 위해서 새로운

발신지 포트를 쓴다. 하지만 사용할 수 있는 발신지 포트의 수는 제한되어 있고

(60,000개로 가정) 2MSL초 동안(120초로 가정) 커넥션이 재사용될 수 없으므로,초

500(60,000 / 120 = 500)로 커 넥 션이 제한된다.

 

서버가 초당 500개 이상의 트랜잭션을 처리할만큼 빠르지 않다면 TIME_WAIT 포트 고갈은 일어나지 않는다

 

포트 고갈 문제를 겪지 않더라도,커넥션을 너무 많이 맺거나 대기 상태로 있는

제어 블록이 너무 많아지는 상황은 주의해야 한다. 커넥션이나 제어 블록이 너무

많이 생기면 극심하게 느려지는 운영체제도 있다

 

 

 

HTTP 커넥션 헤더

HTTP연결은 클라이언트와 서버사이에 프록시, 캐시 다양한 서버들이 올수있다

특정 커넥션에게 어떤 옵션을 주고싶다면 HTTP커넥션헤더에 토큰을 담아 그 커넥션에게 전달할수있다

토큰은 쉼표로 구분되며, 다른 커넥션에게 양도할수없다

 

Connection 헤더는 전송자가 특정 커넥션에만 해당되는 옵션을 지정하게 해준다.

 

Connection 헤더 에는 다음 세 가지 종류의 토큰이 전달될 수 있기 때문에 다소 혼란스러울 수 있다.

• HTTP 헤더 필드 명은,이 커넥션에만 해당되는 헤더들을 나열한다

임시적인 토큰 값은,커넥션에 대한 비표준 옵션을 의미한다.

• close 값은,커넥션이 작업이 완료되면 종료되어야 함을 의미한다.

 

Connection 헤더에 있는 모든 헤더 필드는 메시지를 다른 곳으로 전달하는 시점에 삭제

 

Connection 헤더에는 홉별(hop-by-hop) 헤더 명을 기술

 

홉별 헤더 : 특정 두 서버간에만 영향을 미치고 다른 서버간에는 영향을 미치지않는것

 

수신자가 HTTP 커넥션헤더와 메세지를 함께받으면 다음홉때 전에 있던 커넥션헤더와 그 관련내용들은 다 지워진다

 

 

HTTP커넥션관리를 잘못하면 TCP가 굉장히 느려질수있다

순차적인처리는 물리적지연 + 심리적지연(창에 변화가없는)이 생긴다

게다가 순차적인처리는 내려받을 객체의 크기도 계산해야해서 내려받는동안 창에 변화가없다

 

HTTP커넥션의 성능을 향상시키는 기술 4가지

1. 병렬 커넥션 :여러 tcp커넥션을 이용하여 동시 http 요청

2. 지속 커넥션 : 커넥션 연결/끊기 지연을 방지하기위해 커넥션 재사용

3. 파이프라인 커넥션 : 공유 tcp커넥션을 이용하여 동시 http요청

4. 다중 커넥션 : 요청과 응답 사이를 중재

 

 

병렬커넥션 : 여러 tcp커넥션을 이용하여 동시 http 요청        커넥션 지연(연결시) 겹치게하면 총 지연시간을 줄일수있다

 

항상 빠른것은아니다

1. 네트워크 대역폭이 순차처리하는데도 부족하다면 병렬로 나누면 더 느려질수도있다

2. 웹페이지에 객체가 100개가 넘어간다면 각 사용자가 커넥션 100개를 넘어간다면 서버에 부하가 올수있지만

브라우저는 병렬커넥션을 4개까지만 허용한다         만약 병렬커넥션이 많아진다면 끊어버릴수도있다

 

병렬커넥션은 실제로 더 빨리 내려받는것은 아니지만 여러개를 동시에 내려받으니 빨라보인다

 

 

 

사이트 지역성 : 웹페이지에 http요청을 보내면 그외 다른 이미지를 위해 그 서버에 또 요청을 하게되는것

 

지속커넥션 : 사이드 지역성같은것이 발생할것을 대비해 요청이 처리된후에도 커넥션을 유지하여 앞으로 있을 요청에 사용하는것

 

연결에 의한 지연을 절약할수있고 tcp 느린시작의 지연도 방지하여 더 빠르게 데이터를 보낼수있다

 

 

 

지속 커넥션 vs 병렬 커넥션

 

병렬 커넥션 단점 : 매 트랜잭션마다 새로운 연결을 해야한다 -> 연결지연 발생

tcp 느린시작으로 인해 데이터를 빨리보낼수없다

커넥션의 개수가 제한되어있다 (4)

 

지속 커넥션 장점 : 이전 연결되어있던 커넥션 재사용 -> 연결지연 절약

tcp 느린시작이 이미 튜닝다되어서 데이터를 빨리 보낼수있다

커넥션 개수가 줄어든다

 

병렬 커넥션과 지속 커넥션을 보통 같이쓴다 -> 적은수의 병렬커넥션을 만들고 그것을 지속한다

 

지속 커넥션 종류

HTTP/1.0+ 'Keep alive'

HTTP/1.1 '지속'

 

 

Keep-alive동작

 

클라이언트가 서버에게 요청을 보내기전에 연결을 유지하기위해 커넥션헤더에 Connection:Keep-Alive를 보낸다        서버가 응답에 Connection:Keep-Alive 헤더가 없으면 서버가 지원을하지않아서 연결이 유지되지않는다

 

 

Keep-Alive 옵션

요청에 Connection:Keep-Alive가 있다고해서 반드시 keep-alive를 해줄필요는없다 언제든지 keep-alive를 끊을수있으면 제한할수있따

 

timeout - 값만큼의 시간동안 연결을 유지하고 끊는다 확실하게 보장은할수없다

max - 값만큼의 keep-alive를 처리후 연결유지를 끊는다 확실하게 보장은 할수없다

 

반드시 Connect:Keep-Alive 헤더가 존재해야 옵션을 사용할수있다

 

 

 

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

다음은 keep-alive 커넥션에 대한 몇 가지 제한과 사용 방법에 대한 상세 내용이다.

• keep-alive HTTP/1.0에서 기본으로 사용되지는 않는다. 클라이언트는 keepalive 커넥션을 시용하기 위해 Connection: Keep-Alive 요청 헤더를 보내야 한다.


커넥션을 계속 유지하려면 모든 메시지에 Connection: Keep-Alive 헤더를 포함

해 보내야 한다. 만약 클라이 언트가 Connection: Keep-Alive 헤더를 보내지 않으

면 서버는 요청을 처 리한 후 커넥션을 끊을 것이다.


클라이언트는 Connection: Keep-Alive 응답 헤더가 없는 것을 보고 서버가 응답

후에 커넥션을 끊을 것임을 알 수 있다.


커넥션이 끊어지기 전에 엔터티 본문의 길이를 알 수 있어야 커넥션을 유지할 수

있다. 이 말은 엔터티 본문이 정확한 Content-Length 값과 함께 멀티파트 미디

어 형 식 (multipart media type)을 가지거나 청크 전송 인코딩 (chunked transfer

encoding)으로 인코드 되어야 함을 뜻한다. keep-alive 커넥션에서 잘못된

Content-Length 값을 보내는 것은 좋지 않은데,트랜잭션이 끝나는 시점에 기존

메시지의 끝과 새로운 메시지의 시작점을 정확히 알 수 없기 때문이다.


프락시와 게이트웨이는 Connection 헤더의 규칙을 철저히 지켜야 한다. 프락시

와 게이트웨이는 메시지를 전달하거나 캐시에 넣기 전에 Connection 헤더에 명

시된 모든 헤더 필드와 Connection 헤더를 제거해야 한다.


정석대로라면, keep-alive 커넥션은 Connection 헤더를 인식하지 못하는 프락시

서버와는 맺어지면 안 된다. 이는 뒤에서 설명할 멍청한(dumb) 프락시로 인해

발생할 문제를 예방하기 위한 것이지만,현실적으로 그것이 쉽진 않다.

. 기술적으로 HTTP/1.0을 따르는 기 기로부터 받는 모든 Connection 헤더 필드

(Connection Keep-Alive를 포함)는 무시해야 한다. 오래된 프락시 서버로부터

실수로 전달될 수 있기 때문이다. 실제로,어떤 클라이언트나 서버는 오래된 프

락시에 행(hang)이 걸릴 수 있는 위험이 있음에도 이 규칙을 지키지 않기도 한다.


클라이언트는,응답 전체를 모두 받기 전에 커넥션이 끊어졌을 경우,별다른 문

제가 없으면 요청을 다시 보낼 수 있게 준비 되어 있어야 한다. 그렇지 않으면 요

청 이 반복될 경우 문제가 발생할 수 있다



Keep-Alive와 멍청한(dumb) 프락시

 

c ---> p ---- > s

  <---         <----

 

 

1. 클라이언트가 연결유지하기위해 Connection:Keep-Alive를 보낸다

2. 프락시는 keep-Alive를 이해하지못하기에 그냥 서버에게 보낸다

3. 서버는 keep-Alive를 받고 keep-Alive로 응답을 한다

4. 프락시는 keep-Alive를 이해하지못하기에 그냥 클라이언트에게 보내고 서버와 연결이끊어지길 기다린다

5. 클라이언트는 연결유지가 됐다고 생각한다

6. 클라이언트가 다음에 이 연결에 요청을 보낸다

7. 프락시는 연결유지가 됐다고 이해를못하기에 같은커넥션에 다른요청이 오는것을 예상하지못한다

8. 요청이 프락시로부터 무시가된다

9. 클라이언트 or 서버에서 타임아웃이 되어 끊어질때까지 기다린다

 

커넥션헤더는 홉별헤더로 작성되기때문에 두 서버 (클라이언트 ,프록시) 간에서만 이용되기때문에

다른곳으로 전달해서는 안된다.

 

 

멍청한 프락시문제를 막기위해 프락시헤더를 사용

 

프록시에게 커넥션헤더가 아닌 프록시 헤더를 전달하면 오래된 프록시들도 이것을 인식한다

멍청한 프록시가 이것을 웹서버에게 전달하면 웹서버는 프록시헤더를 무시하고

똑똑한 프록시(프록시헤더가 커넥션헤더의 keep-alive인것을 아는)는 프록시헤더를 커넥션헤더로 변환하여 서버에게 전달한다

 

이렇게함으로써 아무런 문제가 발생하지않는다

 

위방법은 클라이언트와 서버사이에 프록시 서버가 1개만 존재할때 가능하다

 

만약 멍청한 프록시 양 옆에 똑똑한 프록시가 있다면 잘못된헤더를 전송한다

 

c--->P --> S-P --> S

 <--   <--    <--

 

1. 클라이언트가 멍청한 프록시에게 프록시헤더를 전송한다

2. 멍청한 프록시가 프록시헤더를 똑똑한 프록시에게 전달한다

3. 똑똑한 프록시는 프록시헤더를 커넥션헤더로 변환하여 서버에게 전달한다

4. 서버는 응답으로 Keep-Alive를 준다

5. 똑똑한 프록시가 keep-Alive를 멍청한 프록시에게 준다

6. 멍청한 프록시는 keep-Alive를 인식하지못하니 그냥 클라이언트에게 전달한다

7. 클라이언트는 연결유지가 된것으로 생각한다

8. 클라이언트가 같은커넥션으로 요청한다

9. 멍청한 프록시는 연결유지된것을 모르기때문에 서버와 연결이 끊어지기만을 기다리기때문에 요청을 무시한다

 

 

프록시 커넥션을 사용하더라도 프록시서버가 많으면 문제가 생길수있다

게다가 보이지않는 프록시서버들도 있기때문에 브라우저가 프록시커넥션을 보낼수가없다

 

그래서 보이지않는 웹어플리케이션들이 명확하게 지속커넥션을 유지하는게 중요하다

 

 

HTTP/1.1 지속커넥션

http/1.1 keep-alive를 사용하지않는다 모든 커넥션은 기본 지속커넥션을 사용한다

keep-alive보다 지속커넥션이 좀더 잘 동작한다

지속커넥션을 끊으려면 connection:close를 보내야한다

안보낸다고해서 연결이 영원히 지속되는것은아니다

 

 

지속 커넥션의 제한과 규칙

다음은 지속 커넥션에 대한 몇 가지 제한과 사용 방법에 대한 상세 내용이다.

클라이언트가 요청 에 Connection: dose 헤더를 포함해 보냈으면,클라이언트는

그 커 넥 션으로 추가적 인 요청을 보낼 수 없다.

클라이언트가 해당 커넥션으로 추가적인 요청을 보내지 않을 것이라면,마지막

요청 에 Connection: close 헤더를 보내야 한다.

커넥션에 있는 모든 메시지가 자신의 길이 정보를 정확히 가지고 있을 때에만 커

넥션을 지속시킬 수 있다. 예를 들어 엔터 티 본문은 정확한 Content-Length 값을

가지거나 청크 전송 인코딩(chunked transfer encoding)으로 인코드 되어 있어야

한다.

• HTTP/1.1 프락시는 클라이언트와 서버 각각에 대해 별도의 지속 커넥션을 맺고

관리해야 한다.

• HTTP/1.1 프락시 서버는 클라이언트가 커넥션 관련 기능에 대한 클라이언트의

지원 범위를 알고 있지 않은 한 지속 커넥션을 맺으면 안 된다. 앞서 설명했듯이

오래된 프락시가 Connection 헤더를 전달하는 문제가 발생할 수 있기 때문이다.

현실적으로 이것이 쉽지는 않으며,많은 벤더가 이 규칙을 지키지 않는다.

서버는 메시지를 전송하는 중간에 커넥션을 끊지 않을 것이고 커넥션을 끊기

전에 적어도 한 개의 요청에 대해 응답을 할 것이긴 하지만, HTTP/1.1 기기는

Connection 헤더의 값과는 상관없이 언제든지 커넥션을 끊을 수 있다.

• HTTP/1.1 애플리케이션은 중간에 끊어지는 커넥션을 복구할 수 있어야만 한다.

클라이 언트는 다시 보내도 문제가 없는 요청 이라면 가능한 한 다시 보내 야 한다.

클라이언트는 전체 응답을 받기 전에 커넥션이 끊어지면,요청을 반복해서 보내

도 문제가 없는 경우에는 요청을 다시 보낼 준비가 되어 있어야 한다.

하나의 사용자 클라이언트는 서버의 과부하를 방지하기 위해서,넉넉잡아 두 개

의 지속 커넥션만을 유지해야 한다. 따라서 사명의 사용자가 서버로 접근하려 한

다면,프락시는 서버나 상위 프락시에 넉넉잡아 약 2N개의 커넥션을 유지해야

한다.

 

 

파이프라인 커넥션

지속커넥션을 통하여 파이프라이닝 할수있다

요청을 보낸뒤 응답이 도착하기전까지 큐에 요청이 쌓인다 응답이오면 하나씩 큐에서 제거된다

 

파이프라인에는 여러 가지 제약사항이 있다.

• HTTP 클라이언트는 커넥션이 지속 커넥션인지 확인하기 전까지는 파이프라인

을 이어서는 안 된다.

• HTTP 웅답은 요청 순서와 같게 와야 한다. HTTP 메시지는 순번이 매겨져 있지

않아서 웅담이 순서 없이 오면 순서 에 맞게 정 렬시킬 방법 이 없다.

. HTTP 클라이언트는 커넥션이 언제 끊어지더라도,완료되지 않은 요청이 파이프

라인에 있으면 언제든 다시 요청을 보낼 준비가 되어 있어야 한다. 클라이 언트가

지속 커넥션을 맺고 나서 바로 10개의 요청을 보낸다고 하더라도 서버는 5개의

요청만 처리하고 커넥션을 임의로 끊을 수 있다. 남은 5개의 요청은 실패할 것이

고 클라이언트는 예상치 못하게 끊긴 커넥션을 다시 맺고 요청을 보낼 수 있어야

한다.

. HTTP 클라이언트는 POST 요청같이 반복해서 보낼 경우 문제가 생기는 요청은

파이프라인을 통해 보내면 안 된다. 에 러가 발생하면 파이프라인을 통한 요청 중

에 어떤 것들이 서버에서 처리되었는지 클라이언트가 알 방법이 없다. POST

같은 비멱등 요청을 재차 보내면 문제가 생길 수 있기 때문에 문제가 있는 상황에서 그런 위험한 메서드로 요청을 보내서는 안 된다

 

 

커넥션끊기에 대한 미스터리

마음대로 끊기

커넥션을 끊는건 http 서버나 클라이언트 원할때 언제든 끊을수있다

연결이 더이상 요청을 보내지않는 유후상태가되면 끊어도된다

하지만 그 연결에서 더이상 요청을 보내지않을꺼라는 확신은없다

만약 끊었다면 추후에 메세지를 보낼때 문제가 생길수도있다

 

커넥션 끊기 허용, 재시도, 안전메소드?

 

커넥션은 에러가 나지않아도 언제든 연결을 끊을수있다 하지만 파이프라이닝 같이 큐에다 요청을 저장해놓는 방식에서 갑자기 연결이 끊기면되면 큐에 요청이 담긴채로 끊기게되서 부작용이 발생할수있다

그러면 이전에 보냈던 요청에대한 응답이 오기전까지 기다려야하며 다시보낼수있는 기능을 지원하더라도 기다려야한다

파이프라이닝에는 안전한메소드(서버에서 아무일도일어나지않는)는 여러번 반복해서 보내도되지만 post같이 비안전메소드는 반복해서 보내선안된다 반복해서 보냈다가 연결이 갑자기 끊기게되면 어디까지 처리되었는지 모르며 알수없는 결과를 초래하기때문에 에러가발생한다면 기다려야한다

 

 

우아하게 커넥션끊기

 

tcp 커넥션은 양방향 전송이다 양쪽다 입력, 출력이 있다

 

tcp커넥션을 끊는방법은 전체끊기, 절반끊기가 있다

 

보통 http어플리케이션은 전체끊기를 하지만 파이프라이닝을 이용할시에 갑자기 전체다 끊기면 큐에남아있는 요청이 문제가될수있어서 절반끊기가 필요하다

 

절반끊기를할때 출력채널만 닫으면 문제가되지않는다 클라이언트의 입력채널이 살아있으니 출력채널에 데이터를 받다가 닫으면 더이상 오지않을꺼고 그러면 커넥션이 끊겼다는것을 알수있다

 

하지만 입력채널을 닫게되면 문제가된다.

출력채널에서 계속 데이터를 보내는데 입력이 닫혀있으니 받을수가없다 끊겼으니 받을려고하면 'connection reset by peer' 라는 오류가 발생하는데 이건 운영체제가 심각한 에러로 인식하여 아직 읽지않고 남은 버퍼에 내용들을 모조리 지워버린다

 

 

그래서 우아하게 끊기위해서는 먼저 자신의출력부분을 닫고 상대방의 출력부분이 닫힐때까지 기다려야한다

하지만 상대방이 절반끊기를 잘 구현했을거란 보장도없고 절반끊기를 했는지 검사할수도없다

 

그래서 자신의 출력을 닫은후 입력부분에서 데이터 스트림의 끝부분인지 계속 검사를 해야한다 그리고 입력채널이 타임아웃내에 닫히지않는다면 리소스 보호를 위해 강제로 끊을수도있다

728x90
반응형

' > HTTP 완벽 가이드' 카테고리의 다른 글

HTTP 완벽 가이드 5장 웹서버  (0) 2019.03.22
HTTP 완벽 가이드 3장 HTTP 메세지  (0) 2019.03.17
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   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
글 보관함