% uname -a
Linux tomcat_172.31.0.135 5.10.210-201.855.amzn2.x86_64 #1 SMP Tue Mar 12 19:03:26 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
% java -version
openjdk version "17.0.10" 2024-01-16 LTS
OpenJDK Runtime Environment Corretto-17.0.10.8.1 (build 17.0.10+8-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.10.8.1 (build 17.0.10+8-LTS, mixed mode, sharing)
% tomcat version
Server version: Apache Tomcat/8.5.95
Server built: Oct 20 2023 21:57:35 UTC
Server number: 8.5.95.0
OS Name: Linux
OS Version: 5.10.210-201.855.amzn2.x86_64
Architecture: amd64
JVM Version: 17.0.10+8-LTS
JVM Vendor: Amazon.com Inc.
참고로 위는 실습을 진행한 서버의 정보이다.
EC2 > 대상 그룹 > 선택 > 대상 그룹 속성 편집
위 순서로 Sticky session 을 설정할 수 있으며, 한글 콘솔에서는 고정 세션이라 불린다. 고정세션은 라운드 로빈으로 작동하는 로드벨런서에 세션을 고정해서 사용자의 경험을 지속할수 있도록 도와주는 역할을 한다.
# 테스트 페이지를 위한 설정
% cd <tomcat webapps 경로>
% mkdir sample
% cd sample
% vi test.jsp
# 해당 디렉토리를 사용하는 사용자와 그룹으로 권한 수정
% chown -R <사용자>:<그룹> sample/
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<%@ page import="java.text.*"%>
<%@ page import="java.util.*"%>
<%
String RsessionId = request.getRequestedSessionId();
String sessionId = session.getId();
boolean isNew = session.isNew();
long creationTime = session.getCreationTime();
long lastAccessedTime = session.getLastAccessedTime();
int maxInactiveInterval = session.getMaxInactiveInterval();
Enumeration e = session.getAttributeNames();
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Session Test</title>
</head>
<body>
<table border=1 bordercolor="gray" cellspacing=1 cellpadding=0
width="100%">
<tr bgcolor="gray">
<td colspan=2 align="center"><font color="white"><b>Session
Info</b></font></td>
</tr>
<tr>
<td>Server HostName</td>
<td><%=java.net.InetAddress.getLocalHost().getHostName()%></td>
</tr>
<tr>
<td>Server IP</td>
<td><%=java.net.InetAddress.getLocalHost().getHostAddress()%></td>
</tr>
<tr>
<td>Request SessionID</td>
<td><%=RsessionId%></td>
</tr>
<tr>
<td>SessionID</td>
<td><%=sessionId%></td>
</tr>
<tr>
<td>isNew</td>
<td><%=isNew%></td>
</tr>
<tr>
<td>Creation Time</td>
<td><%=new Date(creationTime)%></td>
</tr>
<tr>
<td>Last Accessed Time</td>
<td><%=new Date(lastAccessedTime)%></td>
</tr>
<tr>
<td>Max Inactive Interval (second)</td>
<td><%=maxInactiveInterval%></td>
</tr>
<tr bgcolor="cyan">
<td colspan=2 align="center"><b>Session Value List</b></td>
</tr>
<tr>
<td align="center">NAME</td>
<td align="center">VAULE</td>
</tr>
<%
String name = null;
while (e.hasMoreElements()) {
name = (String) e.nextElement();
%>
<tr>
<td align="left"><%=name%></td>
<td align="left"><%=session.getAttribute(name)%></td>
</tr>
<%
}
%>
</table>
<%
int count = 0;
if(session.getAttribute("count") != null)
count = (Integer) session.getAttribute("count");
count += 1;
session.setAttribute("count", count);
out.println(session.getId() + " : " + count);
%>
</body>
</html>
위는 최초 접근 시 나온 화면이며, 세션ID 를 잘 확인해본다면 7B1699723AD59DDE29E1846E2C028A26 으로 되어 있다.
새로고침을 5번 시도 하였지만 Sticky session 설정으로 세션ID 는 고정이 되어 있는 것을 확인할 수 있다.
시간이 지난 뒤 다시 새로 고침을 하였을 때는 다른 서버로 접근을 하였고, 세션ID 는 EF5457A5B3CD8C22AAD79ED51EB018C3 으로 바뀐 것을 확인할 수 있었다.
이처럼 Sticky session에서는 사용자와 세션 정보를 갖고 있는 서버를 1:1로 매핑해주어 세션 불일치를 해결해지만, 문제가 발생하면 Scale out의 장점인 트래픽 분산과 가용성을 제대로 활용하지 못하게 되는 경우가 발생할 수 있게 된다.
ElastiCache > Redis 캐시 > Redis 캐시 생성
테스트를 위해 위와 같이 설정 하였으며, 방화벽 오픈 등 작업은 진행이 되어야 한다. 또한 서브넷 그룹이나 파라미터 그룹 등은 기본 값으로 진행을 하였다.
# tomcat Redis 설치 및 설정
% cd <tomcat 설치 경로> # Amazonlinux2 기준으로 기본은 /usr/share/tomcat
% mkdir download
% cd download
% wget https://github.com/ran-jit/tomcat-cluster-redis-session-manager/releases/download/2.0.4/tomcat-cluster-redis-session-manager.zip
% unzip tomcat-cluster-redis-session-manager.zip
% cp tomcat-cluster-redis-session-manager/lib/* <tomcat lib 경로>/
% cp tomcat-cluster-redis-session-manager/conf/* <tomcat conf 경로>/
tomcat-cluster-redis-session-manager releases
자세한 릴리즈는 위 github 주소에서 확인하면 된다.
redis-data-cache.properties 파일 6번 라인에서 위와 같이 Elasticache 의 기본 엔드포인트 정보를 추가한다.
web.xml 파일의 637번 라인에서 30 -> 60 으로 수정을 한다.
제일 아래에서 화면과 같은 구문을 추가 한다.
<Valve className="tomcat.request.session.redis.SessionHandlerValve" />
<Manager className="tomcat.request.session.redis.SessionManager" />
Valve란?
* Catalina 컨테이너(Engine, Host, Context)의 요청 처리 파이프라인 상에서 특정 기능을 수행하기 위해 추가될 수 있는 컴포넌트
처음 접속했을 때 세션ID 값이 A03F8E0DE557CB98281E34745CBB3382 인 것을 확인할 수 있었다.
새로고침을 하였고, 접속하는 서버의 IP는 172.31.0.135 -> 172.31.2.61 로 바뀌었지만 세션 ID 는 바뀌지 않은 것을 확인할 수 있었다. (처음 새로고침을 했을 때 동일한 서버로 접근을 하여 다시 시도를 하였기에 3이 찍혔다.)