IT한 것/java

Servlet - Session Clustering, Context Clustering

lovian 2021. 4. 3. 00:15

대부분의 Servlet 개발자 분들은 알고 계실지 모르지만, 알게된 김에 한번 정리해본다.

 

WAS는 instance 별로 정보를 관리한다.

물론 DB에도 중요한 정보를 저장하고 관리한다.

그중 일부 정보는 굳이 DB로 저장할 필요가 없다. (휘발성이어도 어느 조건까지만 유지되면 되는 정보)

 

instance 별로 할 수 있는 작업의 임계치가 존재한다.

이를 극복하기 위해 여러개의 instance를 묶어 전체 적인 임계치를 상승시킨다

 

여기에서 고민거리가 생긴다, instance1에 접속해서 로그인 한 사용자의 다음 HTTP Request는 instance1을 보장 할 수 없는 경우가 발생한다. (web server나 L4에서 보장 해주기도 하지만, 이것을 사용 못하는 경우도 존재함)

그럼 그 사용자가 instance2에서는 로그인 한 정보가 존재하지 않는다. instance1에 있을테니까.

 

Stateless(아주 중요함)인 HTTP는 이 특성을 극복하기 위해 Session을 사용한다.

그리고 Servlet Container(tomcat, weblogic 등등)는 HTTP의 헤더의 쿠키 영역에 JSESSIONID이라는 항목에 일정 값을 넣어 주고 받으면서, 현재 HTTP Request와 이전 HTTP Request의 내부 상태를 유지한다.

 

위의 상황을 이를 빗대어 표현하면

instance1에서 로그인된 JSESSIONID 값이 1이라면, instance2에는 아직 JSESSSIONID 1이란 값이 없으므로 로그인 된 사용자로 판단할 근거가 존재하지 않는다.

 

Servlet은 이런 상태 극복을 위해서 instance 간에 Session 정보를 공유하는 방법을 사용한다.

Servlet 개발시 HttpSession의 getAttribute, setAttribute를 사용해왔다면, WAS의 세션 클러스터링 설정으로 여러대의 WAS instance를 연결해도 아무런 문제 없이 서비스를 동작시킬 수 있다.

 

ServletContext attribute

때로는 개별 세션이 아닌 ServletContext 의  attribute를 사용하기도 한다.

HttpSession 처럼 사용방법은 동일하지만, 의외의 장벽이 존재한다.

 

docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html

 

ServletContext (Java EE 6 )

Instantiates the given EventListener class. The specified EventListener class must implement at least one of the ServletContextListener, ServletContextAttributeListener, ServletRequestListener, ServletRequestAttributeListener, HttpSessionListener, or HttpS

docs.oracle.com

위의 링크를 보면, 이런 내용이 있다.

In the case of a web application marked "distributed" in its deployment descriptor, there will be one context instance for each virtual machine. In this situation, the context cannot be used as a location to share global information (because the information won't be truly global). Use an external resource like a database instead.

web.xml에 distributed로 설정된 web application인 경우, 각 JVM 마다 한 context가 있을 것이다. 이러한 상황에서 context는 글로벌 정보를 공유하는 용도로 사용 할 수 없으니 DB 같은것을 사용하라

 

또 아래의 링크를 보자

stackoverflow.com/questions/12809048/servletcontex-attribute-in-a-clustered-application-environment

 

ServletContex attribute in a clustered application environment

I have my application deployed in a cluster with two servers. When I set any attribute using: this.getServletContext().setAttribute("test", testObj); Will testObj attribute with key test be avail...

stackoverflow.com

Context attributes are local to the JVM in which they were created. This prevents ServletContext attributes from being a shared memory store in a distributed container. When information needs to be shared between servlets running in a distributed environment, the information should be placed into a session (See Chapter SRV.7, “Sessions”), stored in a database, or set in an Enterprise JavaBeansTM component.

servlet 스펙을 보면 위와 같은 내용이 있다고 합니다.

Context attribute는 공유 안되니까, 세션에 넣거나 DB나 JavaBeans등에 넣으세요.

 

조금 더 찾아보면 나오지만, 그럼에도 Context attribute 가 clustering되는 WAS는 존재합니다.

 

때문에 내가 만들 Web application이 특정 WAS에서 동작하는 것이라면, 해당 WAS가 Context clustering을 지원하는지 확인이 된다면, context attribute를 이용하여 공유를 해도 됩니다.

 

저는 이런거 싫어해서 모두 포기하고 DB에 넣었다는 삽질 결말입니다.