병렬 커넥션이 일반적으로 빠름
But, 복잡한 웹 페이지에서는 수많은 객체와 함께 사용자의 요청도 함께 처리해야하기 때문에 너무 많은 커넥션을 서버가 떠안게 되어 오히려 서버의 성능을 떨어뜨림
Ex. 백명의 가상 사용자가 각각 100개의 커넥션을 맺고있다면, 서버는 총 10,000개의 커넥션을 떠안게 됨
병렬 커넥션이 항상 더 빠른 것은 아니지만,
사용자 입장에서는 /
병렬 커넥션을 사용하게 되면 화면에서 여러가지 작업이 일어나는 것을 한 눈에 확인할 수 있기 때문에 더 빠르다고 느낄 수 있음
클라이언트나 서버가 커네견을 끊기 전까지는 트랜잭션 간에도 커넥션 유지
해당 서버에 이미 맺어져있는 지속 커넥션을 사용함으로써
But, 지속 커넥션을 잘못 관리할 경우, 계속 연결된 상태로 있는 수많은 커넥션들이 쌓임
--> 로컬의 리소스, 원격의 클라이언트와 서버의 리소스에 불필요한 소모 발생
지속커넥션은 병렬 커넥션과 함께 사용될 때 가장 효과적
dumb 프락시에서 1번을 사용할 때 발생하는 문제
프락시는 http의 connection 헤더를 단순히 확장 헤더로 취급하여 이해하지 못함
따라서 일단 클라이언트에게서Connection: Keep Alive헤더를 포함한 요청을 보내게 되면 그대로 서버에게 보냄
그럼 서버는 아 연결을 유지하고 싶어하는구나 생각해서 다시 그대로 헤더에Connection: Keep Alive포함해서 응답 보냄
여기서도 프락시는 이 말을 이해하지 못하고 클라이언트에게 보냄
여기까지 보면 클라이언트와 서버는 둘 다 커넥션을 유지할것임을 인지하고 있으므로 서버가 커넥션을 끊지 않음
But, 프락시는 몰라서 서버가 이 커넥션을 끊기를 기다림 멍청한 것
따라서 클라이언트가 커넥션이 유지되고 있는 해당 프락시에게 다른 요청을 또 보내면,
프락시는 왜 똑같은 커넥션으로 요청이 또 오지? 생각해서 그걸 무시함
그러면 브라우저는 해당 요청에 대한 응답을 계속 기다리면서 로드 중이라는 표시만 뜨게 함
이러다가 자신이나 서버가 타임아웃으로 커넥션이 끊길 때까지 기다리게 됨
--> 이런 문제를 발생시키지 않으려면, 프락시가 Connection 헤더와 거기에 명시된 헤더들은 삭제하고 전달해야함
-> 그런데 여기서 궁금증 ! (110P)
어차피 그냥 전달해도 프락시가 이해를 못해서 연결 유지를 이해하지 못한다고 했는데,
지워서 전달한다고 해도 어차피 커넥션은 유지되어있고, 프락시는 이해 못해서 또 요청 무시하는 거 아닌가?
아 그리고 해당 헤더를 지워서 서버에게 전달하면 커넥션을 유지하겠다는 요청을 어떻게 알아듣지?
전달받은 서버가 자신과 프락시 간의 커넥션에 대한 것으로 오해하면서 문제가 생기는 것이라고 했는데(111p)
이게 뭔말이지 클라이언트-서버 간으로 인식하는 게 아닌 건가
클라이언트가 예상치 못하는 시점에 커넥션이 끊어졌을 때를 위해 준비해야한다느 말을 몇번을 말하는 거야
--> 요청들을 큐에 쌓아 놔서 중간에 커넥션이 끊겨도 거기부터 다시 보낼 수 있도록 대비하는 거야
클라이언트가 요청들을 보내면 그에 대한 응답이 오기 전까지는 큐에 쌓여있음
( 중간에 커넥션이 끊겨 요청이 유실되는 것을 방지하기 위해 )
--> 대기시간이 긴 네트워크 상황에서 네트워크 상의 요청-응답 왕복으로 인한 시간을 줄여 성능을 높임
병렬 커넥션
- 각 요청-응답 당 하나의 커넥션으로 동시에 실행
지속 커넥션
- 하나의 커넥션을 유지하면서, 요청-응답을 반복
파이프라인 커넥션
- 하나의 커넥션을 유지하면서, 각 요청에 대한 응답을 기다리지 않고 연속적으로 요청
클라이언트 - 지속 커넥션이 맞는지 확인 전까지는 파이프라인을 이어서는 안됨
( 요청을 응답이 오기 전에 막 보내면 안됨 )
응답들은 요청의 순서들과 같게 와야 함
( 순서에 맞게 정렬시킬 방법 X )
클라이언트 - 커넥션이 언제 끊어지더라도 응답을 못받은 요청을 다시 보낼 준비 되어있어야 함
비멱등성을 가진 요청은 파이프라인을 통해 보내면 안됨
( 클라이언트의 경우, 커넥션이 끊겨 응답을 못받은 요청들이 서버에서 얼만큼 처리되고 있었는지 알 수 없음 - 멱등성을 가진 요청들은 상관이 없는데 비멱등성을 가진 요청은 결과가 변할 수 있기 때문에 파이프라인 커넥션으로 보내지 말아야함 )
멱등(Idempotent)
- 연산을 여러번 수행하더라도 결과가 변하지 않는 특성
멱등성을 가진 메서드 - GET,HEAD,PUT,DELETE,TRACE,OPTIONS
비멱등
- 연산이 한 번 일어날 때마다 결과가 변하는 특성
비멱등성을 가진 메서드 - POST
Ex. 대부분의 브라우저는 캐시된 POST 요청 페이지를 다시 로드하려고 할 때, 요청을 다시 보내길 원하는지 묻는 대화상자를 나타냄
Ex. 물건 주문 페이지에서 다시 로드하면, 해당 주문 요청을 다시 보내시겠습니까? 이런거
각 HTtp 응답은 본문의 정확한 크기와 값을 가지는 Content-Length 헤더를 가지고 있어야 함
클라이언트나 프락시가 커넥션이 끊어졌다는 Http 응답 받은 후에, Content-Length가 실제 길이와 같지 않거나 존재하지 않으면 서버한테 물어봐야함
수신자가 캐시 프락시일 경우에는, 잠재적인 에러가 복합적으로 발생하는 것을 최소화하기 위해 캐시하면 안됨
TCP 커넥션은 양방향임
클라이언트 -> 서버로 요청하는 경우에는 출력 -> 입력의 큐
서버 -> 클라이언트로 응답하는 경우에는 출력 -> 입력의 큐
전체 끊기
절반 끊기
But, 절반 끊기를 안전하게 하기 위해서는 출력 채널을 끊어야함
처음으로 지나가는 통로를 끊어야 반대 쪽에서도 아예 데이터 전송 자체가 안오기 때문에 커넥션이 끊어졌다는 것을 알 수 있음
입력 채널을 끊는 것은 위험
-> 클라이언트가 데이터를 더 보낼지 모르기 때문에 위험
이미 끊긴 입력 채널에 데이터를 전송하게 되면 서버의 운영체제는 TCP connection reset by peer 메세지를 클라이언트에게 보냄
( 심각한 에러로 취급 )
--> 버퍼에 저장된, 아직 읽히지 않은 데이터를 모두 삭제
( 파이프라인 커넥션에서 더 악화 )
( --> 응답 데이터가 기기에 잘 도착하였더라도, 아직 읽히지 않은 버퍼에 있는 응답 데이터들은 사라지게 됨
119p에 이미 응답은 운영 체제의 버퍼에 있지만 아직 애플리케이션이 읽지는 않았다고 가정하자는데
이게 무슨 말이지?
--> 우하하게 커넥션 끊기란
자신의 출력 채널을 먼저 끊고 다른 쪽에 있는 기기의 출력 채널이 끊기는 것을 기다리는 것.
절반 끊기를 하고 난 후에도 데이터나 스트림의 끝을 식별하기 위해 입력 채널에 대해 주기적으로 상태 검사를 해주어야함