[ 글을 작성한 배경 ]
[ 문제 상황 ]
[ 해결 ]
Sticky Session이란 클라이언트의 요청으로 생성된 was에 전달하는 방식을 의미를 한다. 세션 정보가 없는 유저가 요청을 한 경우 로드밸런서의 기본 알고리즘대로 요청을 전달한다.
Sticky Session경우 사용자에 대한 세션이 생성된 서버로 고정이 된다. 이때 이것을 판별하는 방식은 쿠키, IP를 기반으로 판단한다.
세션 정합성 , 캐싱
기존의 세션 불일치를 특정 서버로 전송하며 세션 정합성을 맞추며 캐싱을 통하여 더 빠른 응답 속도를 가질 수 있다.
고립성
사용자가 특정 서버와의 세션을 유지하면서 애플리케이션에 영향을 주지 않는다. 이를 통하여 세션 간의 간섭이 줄어들어 애플리케이션의 안전성을 향상을 시킨다.
성능 저하, 로드 밸런서 목적 실패
처음으로는 특정 서버에 트래픽이 집중될 경우 성능에 문제가 발생한다. 로드 밸런서의 목적은 부하를 적절하게 분산이다. 하지만 Sticky Session으로 인한 한 서버에 부하가 몰리면 로드 밸런서의 목적을 달성할 수 없다.
에러 분산, 세션 유실
하나의 서버에 장애가 발생하면, 해당 서버가 가지고 있는 세션 정보의 유실된다. 이러면 다시 로그인을 해야되는 가용성의 문제를 가지게 된다.
위에 sticky session은 각 서버에 세션을 저장하고 사용자를 해당 was로 보내어 오히려 성능이 안좋아지는 결과를 만들 수 있다. 세션 클러스터링 방식은 세션을 각 서버에 저장이 아닌 데이터를 복사해 데이터를 전파해 가져다 쓸 수 있는 방식이다.
클러스터 내의 모든 서버들이 세션을 공유할 수 있도록 하는 방식으로 방식에는 크게 all-to-all session replication, primary-secondary session replication방식이 있다.
이론적 무제한 확장
이론적으로 제한없이 확장할 수 있다. 서비스 확장 가능하게 디자인된 경우 더 많은 노드를 추가하여 제한없이 증가할 수 있다. 쉽게 조정하고 리소스에 대한 비용만 지불하면 된다.
아키텍처 동일성 유지
소프트웨어 아키텍처가 동일하게 유지, 그에 따라서 프로그램 난이도가 스케일아웃에 비해서 상대적으로 단순하다.
세션 세팅의 어려움
스케일 아웃 관점에서 새로운 서버를 만들 때 기존에 존재하는 was에 새로운 서버 ip/port를 입력해야되는 불편함이 있다.
추가 메모리 사용
서버마다 동일한 세션을 가지고 있어야 하기 때문에 서버가 확장될 수록 복제해야 할 세션 데이터가 늘어나 오버헤드로 이루어진다.
시차로 인한 세션 불일치
세션 전파 작업 중 모든 서버에 세션이 전파되기까지의 시간차로 인하여 세션 불일치의 문제가 발생할 수 있다.
implementation'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.session:spring-session-jdbc'
spring.session.store-type=jdbc
spring.session.jdbc.initialize-schema=always
CREATE TABLE SPRING_SESSION (
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID)
);
CREATE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (LAST_ACCESS_TIME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES LONGVARBINARY NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE
);
CREATE INDEX SPRING_SESSION_ATTRIBUTES_IX1 ON SPRING_SESSION_ATTRIBUTES (SESSION_ID);
spring:
datasource:
data: classpath:schema-h2.sql # Spring Session 테이블 스키마 적용
jpa:
show-sql: true # JPA로 생성되는 쿼리 확인
hibernate:
ddl-auto: create # 프로젝트 시작시 테이블 생성
h2:
console:
enabled: true
path: /h2-console # h2 db 웹 클라이언트 접속 url
devtools:
livereload:
enabled: true # 정적파일들의 실시간 갱신
EnableJdbcHttpSession
어노테이션을 추가를 시킨다.@EnableJdbcHttpSession
public class AppConfig {
}
그런데 byte[]로 attribute_bytes를 저장하는데 어떻게 가져올 수 있니?
byte로 저장하기 때문에 나는 이것을 가져오기 위해서는 Serializable
를 통해서 객체를 저장하면 쉽게 가져올 수 있다.
Serializable
는 자바에서 지원되는 인터페이스 중 하나로 인스턴스를 직렬화할 수 있게 해준다. 이를 통해서 객체 상태를 바이트 스트림으로 변환하여 저장할 수 있다.
따라서 해당 클래스는 객체를 역, 직렬화를 할 수 있게 된다. 이를 통하여 byte[]를 추가적인 설정을 할 필요없이 객체를 가져올 수 있습니다.
public class Member implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private int age;
// 생성자, 게터, 세터 등 필요한 메서드들
// 예시로 멤버 객체를 생성하고 세션에 저장하는 메서드
public static Member createMember(String username, int age) {
Member member = new Member();
member.setUsername(username);
member.setAge(age);
return member;
}
}
@RestController
public class SessionController {
@Autowired
private SessionRepository<?> sessionRepository;
@GetMapping("/saveMemberToSession")
public void saveMemberToSession() {
// 멤버 객체 생성
Member member = Member.createMember("김무건", 28);
// 세션에 멤버 객체 저장
Session session = sessionRepository.findById("sessionId"); // 세션 ID를 실제 세션의 ID로 대체해야 합니다.
session.setAttribute("memberAttribute", member);
sessionRepository.save(session);
}
@GetMapping("/getMemberFromSession")
public Member getMemberFromSession() {
// 세션에서 멤버 객체 가져오기
Session session = sessionRepository.findById("sessionId"); // 세션 ID를 실제 세션의 ID로 대체해야 합니다.
return (Member) session.getAttribute("memberAttribute");
}
}
다중 서버에서 세션의 불일치를 해결하는 방법에는 여러가지가 있다. 이 중에서 세션 스토리지에서 Redis를 통해서 높은 성능을 가질 수 있지만 현재 서비스의 상황에 따라서 다양한 방식을 선택할 수 있다.
RDBMS에서 세션을 저장하면 지속적으로 세션을 탐색, 삭제를 통하여 세션 정합성을 맞추며 데이터를 byte기반으로 저장하여 보안성을 가져갈 수 있다.
https://hyuntaeknote.tistory.com/6