카테고리 없음

AWS | 고가용성 구성에서 세션을 유지하는 3가지 방법

Arthur Kim 2023. 7. 21. 15:43

AWS에서 고가용성 구성에서 세션을 유지하는법

  1. sticky session 옵션을 사용하여 체결된 App Server와만 연결을 유도한다.
  2. DocumentDB에 세션정보를 저장하여 세션을 영구적으로 남긴다.
  3. ElastiCache for redis를 이용하여 세션 정보를 캐싱하여 사용한다.

고가용성 환경에서 세션 유지 문제점

HA Session Problem

  • 1번째 요청에서 App Server 1과의 세션이 체결되었다.
  • 로드밸런서의 트래픽이 두번째 요청을 App Server 2로 보내게 된다면, 1번째 요청에서 체결한 세션을 찾을 수 없는 문제점이 생기게 된다.

유지되지 않는 세션 테스트

session cache failed

  1. 5A로 시작하는 세션키로 유저 정보 저장.
  2. 5A를 세션키로 세젼정보 ( 유저 정보 ) 불러오기.
  • 같은 세션키로 접근하여도 한번은 null을 가져오고, 한번은 정상적으로 불러온다.
  • 이는 로드밸런서 ( ALB )가 한번은 세션이 채결된 App Server 1로 보내주고, 한번은 세션이 채결되지 않은 App Server 2로 보내주기 때문이다.

1. Sticky Session

  • 로드밸런서의 Sticky Session 옵션을 설정하는 방법은 대상그룹 ( Target Group )에서 설정할 수 있다.

Stickiness 사용 ( EC2 > 로드 밸런싱 > 대상그룹 )

sticky-session-004

Sticky Session | 결과

sticky-session-005

  • 세션 정보를 업데이트 하고
  • GET 으로 세션정보를 가져올 때 항상 세션정보를 잘 가져옴을 알 수 있다.

Sticky Session | 장점

가장 쉬운 적용방법

  • 콘솔에서 적용하는 것 이외의 별다른 조치를 취하지 않더라도 즉시 적용가능하다.

높은 적용성

  • 해당 인스턴스가 인스턴스 내부 메모리 ( 인스턴스 스토어 ) 를 이용해서 프로세스를 처리하는 중에 있는 등의 비이상적인 여러 상황속에서도 적용가능하다.

Sticky Session | 단점

로드밸런서의 성능 저하

  • 초기 당면한 세션 비고정되는 문제는 해결하였지만, App Server 1과 2에 균등하게 트래픽을 분산 시켜줘야하는 로드밸런서는 세션 고정으로 인해 트래픽 불균형이 일어 날 수 있다.
  • 예를 들어, App Server 1과 세션이 체결된 사용자들이 오래 서비스를 사용하고 있다면 App Server 2는 그만큼 트래픽을 받지 못하는 상황이 오게된다.

재해발생 시 복구 불가능

  • 세션은 Default 구성으로 인스턴스내의 파일에 세션이 저장된다.
  • 즉, App Server 1의 서비스가 중단 될 경우, App Server 1과 체결된 세션은 모두 강제로 종료되는 상황이 벌어지게 된다.

 


2. DocumentDB

docu session

  • Spring Session MongoDB ( AWS의 DocumentDB는 MongoDB와 호환된다. )를 이용하여 NoSql DB를 세션저장소로 이용할 수 있다.

DocumentDB 생성

docudb-001

  • DocumentDB의 파티션키는 검색속도와 연관 됨으로, 고유한 값으로 지정한다.

pom.xml에 Spring Session 의존성 주입

<dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-core</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-data-mongodb</artifactId>
</dependency>

Spring Boot에 DocumentDB 연동

  • application.properties
spring.data.mongodb.host={{ Your DocumentDB DNS URL }}
spring.data.mongodb.port=27017
spring.data.mongodb.database=prod
  • HttpSessionConfig.java
@EnableMongoHttpSession
public class HttpSessionConfig {
    @Bean
    public JdkMongoSessionConverter jdkMongoSessionConverter() {
        return new JdkMongoSessionConverter(Duration.ofMinutes(30));
    }
}

DocumentDB | 장점

영속성

  • 한번 저장한 세션은 DB에 영원히 저장되어 향후 세션을 이용한 분석 등을 하기에 적합하다.

NoSql의 장점

  • Spring Session에서는 관계형 데이터 베이스도 지원하지만,
  • 그에 비해 DocumentDB를 이용하게 되면 스키마를 자유롭게 확장 시킬수 있고, 용량은 수평 확장이 가능하다

DocumentDB | 단점

I/O 성능

  • 메모리가 아닌 디스크를 이용하기 때문에 세션을 읽고 쓰는데 드는 시간이 높다.

MongoDB와 호환성

  • 기본적으로 DocumentDB는 MongoDB를 호환하지만, 최신 버전을 지원하지 않는다.
  • 3.6 및 4.0 API 과 호환 ( 현재 MongoDB의 최신 버전은 5버전 이상이다. )
  • 추가적으로 DocumentDB보다 더 높은 성능의 DynamoDB도 지원하지만, DynamoDB는 Spring Session 과의 호환이 되지 않는다.

3. ElastiCache For Redis

redis session

AWS | Elasticache for redis 생성하기

ElastiCache > Redis > 생성

redis-005redis-006redis-007

VPC와 서브넷 설정

redis-009redis-010redis-011

  • App Server 1,2가있는 VPC내에서 프라이빗 서브넷 2개 ( 2곳의 다른 가용영역 )에 배치하여 클러스터 구성

정상 생성 확인하기

redis-014

  • 기본엔드포인트가 Spring Boot에서 사용할 Redis의 엔드포인트가 된다.

Spring Session에서 Redis 설정하기

  • 전체 소스는 spring-redis 폴더에 있습니다.

pom.xml

  • spring-boot-starter-data-redis, spring-session-data-redis 의존성 추가
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

application.yaml

spring:
  redis:
    host: << Your Redis Server >>
    port: 6379
    #    password: mypass
    pool:
      max-idle: 8
      min-idle: 0
      max-active: 8
      max-wait: -1

RedisSessionConfig.java

  • host,port의 기본 값은 각각 localhost, 6373 이다.
  • Elasticache 에서 Redis를 올릴때 ConfigureRedisAction에서 문제가 있어서 옵션 없음으로 선택한다 ( NO_OP )
Spring Session using Lettuce connecting to AWS ElastiCache Redis

Spring Session using Lettuce connecting to AWS ElastiCache Redis

@EnableRedisHttpSession
public class RedisSessionConfig {

    @Value("${spring.redis.host}")
    private String redisHost;

    @Value("${spring.redis.port}")
    private int redisPort;

    @Bean
    public LettuceConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory(redisHost, redisPort);
    }

    @Bean
    public ConfigureRedisAction configureRedisAction() {
        return ConfigureRedisAction.NO_OP;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory());
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        return redisTemplate;
    }

}

ElastiCache For Redis | 결과

elastic-redis-session

ElastiCache For Redis | 장점

NoSql Database로서의 장점

  • DocumentDB를 이용하는 것과 마찬가지로 스키마의 자유로운 확장과 용량의 수평확장이 가능한 장점이 있다.

In-Memory 기반의 높은 I/O 성능

  • DocumentDB는 세션을 Disk에 저장하는데 반해 Redis는 메모리에 저장하는 데이터베이스이므로 읽기/쓰기 성능적인 면에서 상당한 이점이 있다.

비용

  • RDS나 DocumentDB를 사용하는것보다 다소 저렴하다. ( 단, 프리티어가 없고 클러스터 구성에따라 차이가 있을 수 있음 )

요금 비교 ( 서울 리전 | 온디멘드 | t3.medium )

인스턴스 종류 크기 시간당 요금
EC2 t3.medium 0.052 USD
Elasticache For Redis cache.t3.medium 0.099 USD
RDS for MySql db.t3.medium 0.104 USD
DocumentDB db.t3.medium 0.119 USD

ElastiCache For Redis | 단점

장애시 복구 불가능

  • In-Memory 방식의 데이터베이스이기 때문에 운영 중 장애가 났을경우 모든 세션 데이터는 사라지게 된다.

Redis와의 호환성

  • 기본적으로 Redis와 동일시 취급받기는 하지만, Configuration 설정에서 오류가 난다는지 하는 기존 Redis와의 자잘한 이슈들은 계속 리포트 되고있다.

비영속성

  • 만료일을 지정하게 되면 해당 만료일이 지나면 데이터는 사라지게된다.
  • 별도의 DB구성이 없다면 세션데이터는 영속성을 갖기 않는다.