jetty의 성능에 대해 알아야 할 필요성이 있어 자료를 찾다가 아래를 발견
http://www.webtide.com/downloads/whitePaperAjaxJetty.html
(webtide에 register, login 후 볼 수 있음)
그래서 정리함.
introduction
web 2.0 나오면서 ajax& comet의 조합이 많이 나오는데,
저 조합을 채택하면 확장성 있는 시스템 만들기가 꽤 어렵다.
그래서 jetty 6 서버에서는 저런 것들을 어떻게 처리하는지 이 paper에서 살펴보자.
Servlet Threading
Thread per connection
커넥션 하나당 쓰레드 하나를 할당하는 모델에 대해 본자.
HTTP 1.0에서 1.1으로 넘어오면서 keepalive를 사용하여 커넥션을 처리하는 패턴을 변경할 수 있다.
그래서 high rates request는 잘 처리할 수 있으나, 동시에 처리할 수 있는 유저수가 떨어진다.
Thread per request
request 하나당 쓰레드 하나 모델에 대해 보자.
NIO가 나온이후에 커낵션 하나에 쓰레드 하나를 계속 할당할 필요가 없이,
커낵션에 데이터가 왔다갔다 할 때만 select에서 event를 받아서 처리하면 된다.
그래서 처리 효율이 올라가고 확장성도 늘어났다. 커낵션 하나당 쓰레드 하나를
할당할 필요가 없어서 더 많은 동시유저를 처리할 수 있게 되었다.
The Ajax/Comet Problem
브라우저가 서버에게 request만 날리는 상황에서는 thread per request가 잘 맞아떨어지는데, comet에서는 사용자의 사용행태가 high rates request가 예상되므로
thread per request과 comet의 궁합이 거시기 하다.
그리고 comet에서는 서버가 long standing request를 유지해야 하므로 thread-per-request
모델과는 커낵션 사용행태에 대한 가정 자체가 완전 다르다.
이 단락에 있는 표는 일반적인 java servlet(synchronous servlet)에서 comet을 구현할 경우
x된다는 사실을 예상하게 하는 예상 리소스 사용량이다.
그러나 comet도 아무생각 없이 일반 java servlet server에서 처리될 수 있으면 확장성이 좋아질 거 같다.
이렇게 되려면 기존의 thread-per-request 모델이 thread-per-active-request 모델로 변경되면 가능해진다.
The Problem of waiting servlets.
위와 같은 connection 처리 모델에서 발생하는 문제 외에도,
서버내에 병목현상을 유발하는 리소스가 있으면 servlet이 block될 수 있다.
(이 내용이 왜 있는지는 모르겠으나, jetty에서 이런 것도 해결해 준다는 걸 설명하기 위함인듯....)
Solutions implemented in jetty 6
NIO Connectors
jetty는 NIO를 사용한다. 그래서 active-request는 thread-per-request 모델로 해결한다.
Continuations
long standing request의 경우을 위해 Continuation 매커니즘을 jetty에서 제시하고 있다.
WaitingContinuation는 wait()로 중지될 수 있고, notify()로 재게될 수 있어서
long standing request의 경우 thread-per-request처럼 thread에 할당하지 않고
continuation으로 처리한다.
continuation은 wait()으로 처리가 중지될 경우 특별한 종류의 RuntimeException을 발생시켜서 long standing reqeust를 Filter/ReqeustDispatcher/Servlet 체인에서 제외시키서 서블릿 컨테이너의 stack에서 제외시켜버린다. 이후에 jetty는 중지된 long standing request를 notify()에 의해 제게되거나, timeout이 발생할 때까지 가지고 있는다.
이런식으로 해서 long standing request가 실행되는 순간에만 resource가 할당되어 실행되고, 아무런 이벤트 없이 기다리는 시간에는 long standing request에 어떠한 resource도
할당되지 않게 한다.
이 장에 있는 그림은 comet에 continuation을 적용하였을 때의 리소스 사용량을 추산한 것이다.
split buffers
servlet에서 실행될 때에만 buffer를 할당해준다. 그래서 메모리 사용량을 줄여보겠다.
waiting 하고 있는 얘들한테는 어떠한 resource도 연결 안 시키겠다는 내용인것 같다.
Delayed Dispatch
tcp패킷은 나누어져서 올 수 있기 때문에 head만 읽고 body가 예상하여
즉시 long standing request를 notify()시켜버리면 body가 도착안 한 경우
상황이 거시기 해질 수 있다.
그러므로 head와 body를 다 받은 후 long standing request가 받은 내용을 즉시 처리할 수 있을 때에만 에 notify()하겠다.
Conclusion
was에서 comet도 부드럽게 처리할 수 있는 아키텍쳐를 수립했다. |