2008년 08월 01일
자바 서블릿 컨테이너의 Comet 지원 3 - Resin
이전글
Resin 은 버전 3.1에서 Comet 모델을 지원한다. Tomcat 과 마찬가지로 javax.servlet.Servlet 을 확장한 인터페이스를 제공하는 방식이다. com.caucho.servlet.comet.CometServlet 이 그것인데 이 인터페이스에는 다음과 같은 메서드들이 있다.
Tomcat 과 마찬가지 방식으로 이 인터페이스를 구현한 서블릿은 요청을 처리할 때 기존 서블릿의 service 메서드를 호출하지 않고 이 인터페이스의 service 메서드를 호출한다. service 메서드의 호출 결과가 true 가 되면 요청 처리는 suspend 되고 스레드는 풀로 되돌아간다. CometController 의 wake 메서드를 호출하면 요청 처리는 재개되어 resume 메서드가 실행된다. resume 메서드가 true 를 반환하면 또 다시 suspend 되어 wake 를 기다리게 되고 false 를 반환하면 요청 처리가 끝나게 된다.
service, resume 메서드에 인자로 들어오는 CometController 객체는 service, resume 그리고 다른 이벤트 대기 스레드 사이에서 공유하여 신호를 보낼 수 있고(wake 메서드) 서로간 데이타 교환을 할 수도 있다(setAttribute, getAttribute).
Jetty 나 Tomcat 과는 어떻게 다른지 같은 채팅 예제로 실제 사용법을 알아보겠다. ChatServlet 과 chat.jsp 는 Jetty 의 경우와 같고 BroadcasterServlet 은 다음과 같다.
service 메서드에서 최초 요청 처리를 처리하면서 인자로 넘어온 CometController 객체를 messageSender 객체에 저장하여 이벤트 처리 스레드로 넘긴다. 이후 CometController 의 wake 메서드가 호출되면 resume 이 실행되고 여기서 실제 데이타를 전송한다. 전송할 데이타는 이벤트 처리 스레드에서 CometController.setAttribute 으로 넘기고 여기서는 getAttribute 로 받는다.
다음은 MessageSender 클래스이다.
MessageSender 는 Jetty 의 경우와 비슷하다. CometController 들을 sessions 에 저장해 두고 채팅 메시지가 들어오면 이를 CometController 에 저장(setAttribute) 한 후 wake 를 호출해서 요청 처리가 resume 되게 한다.
Resin 의 Comet 지원은 Jetty 와 비교하면 직관적으로 이해하기 쉽다. 또한 Tomcat 처럼 번거롭지도 않다. 세 서블릿 컨테이너의 Comet 지원 중에서 가장 사용하기가 쉬운 것 같다.
Resin 은 버전 3.1에서 Comet 모델을 지원한다. Tomcat 과 마찬가지로 javax.servlet.Servlet 을 확장한 인터페이스를 제공하는 방식이다. com.caucho.servlet.comet.CometServlet 이 그것인데 이 인터페이스에는 다음과 같은 메서드들이 있다.
public interface CometServlet extends Servlet {
boolean service(ServletRequest request, ServletResponse response,
CometController controller) throws ServletException, IOException;
boolean resume(ServletRequest request, ServletResponse response,
CometController controller) throws ServletException, IOException;
}
Tomcat 과 마찬가지 방식으로 이 인터페이스를 구현한 서블릿은 요청을 처리할 때 기존 서블릿의 service 메서드를 호출하지 않고 이 인터페이스의 service 메서드를 호출한다. service 메서드의 호출 결과가 true 가 되면 요청 처리는 suspend 되고 스레드는 풀로 되돌아간다. CometController 의 wake 메서드를 호출하면 요청 처리는 재개되어 resume 메서드가 실행된다. resume 메서드가 true 를 반환하면 또 다시 suspend 되어 wake 를 기다리게 되고 false 를 반환하면 요청 처리가 끝나게 된다.
service, resume 메서드에 인자로 들어오는 CometController 객체는 service, resume 그리고 다른 이벤트 대기 스레드 사이에서 공유하여 신호를 보낼 수 있고(wake 메서드) 서로간 데이타 교환을 할 수도 있다(setAttribute, getAttribute).
Jetty 나 Tomcat 과는 어떻게 다른지 같은 채팅 예제로 실제 사용법을 알아보겠다. ChatServlet 과 chat.jsp 는 Jetty 의 경우와 같고 BroadcasterServlet 은 다음과 같다.
BroadcasterServlet.java
...
@Override
public boolean service(ServletRequest request, ServletResponse response,
CometController controller) throws ServletException, IOException {
HttpServletResponse res = (HttpServletResponse) response;
res.setContentType("text/html; charset=utf-8");
messageSender.addSession(controller);
return true;
}
@Override
public boolean resume(ServletRequest request, ServletResponse response,
CometController controller) throws ServletException, IOException {
messageSender.removeSession(controller);
String message = (String) controller.getAttribute("message");
HttpServletResponse res = (HttpServletResponse) response;
PrintWriter out = res.getWriter();
out.println(message);
res.flushBuffer();
return false;
}
...
service 메서드에서 최초 요청 처리를 처리하면서 인자로 넘어온 CometController 객체를 messageSender 객체에 저장하여 이벤트 처리 스레드로 넘긴다. 이후 CometController 의 wake 메서드가 호출되면 resume 이 실행되고 여기서 실제 데이타를 전송한다. 전송할 데이타는 이벤트 처리 스레드에서 CometController.setAttribute 으로 넘기고 여기서는 getAttribute 로 받는다.
다음은 MessageSender 클래스이다.
MessageSender.java
public class MessageSender implements Runnable {
private final BlockingQueue<String> messages =
new LinkedBlockingQueue<String>();
private final Set<CometController> sessions =
new CopyOnWriteArraySet<CometController>();
private volatile boolean running = true;
public void stop() {
this.running = false;
}
public void sendMessage(String message) {
try {
messages.put(message);
} catch (InterruptedException ignore) {
// ignore
}
}
public void addSession(CometController controller) {
sessions.add(controller);
}
public void removeSession(CometController controller) {
sessions.remove(controller);
}
@Override
public void run() {
while (running) {
String message = null;
try {
message = messages.take();
} catch (InterruptedException ignore) {
// ignore
}
for (CometController controller : controllers) {
controller.setAttribute("message", message);
controller.wake();
}
}
}
}
MessageSender 는 Jetty 의 경우와 비슷하다. CometController 들을 sessions 에 저장해 두고 채팅 메시지가 들어오면 이를 CometController 에 저장(setAttribute) 한 후 wake 를 호출해서 요청 처리가 resume 되게 한다.
Resin 의 Comet 지원은 Jetty 와 비교하면 직관적으로 이해하기 쉽다. 또한 Tomcat 처럼 번거롭지도 않다. 세 서블릿 컨테이너의 Comet 지원 중에서 가장 사용하기가 쉬운 것 같다.
# by | 2008/08/01 09:35 | 트랙백














