sixth - HJ-Rich/2022-MyRSS GitHub Wiki


6차 데모 요구사항

hikariCP 커넥션풀 설정

  • 수치를 설정하고 정한 이유를 발표한다
  • hikariCP configuration 보고 필요한 값 설정한다
  1. 풀 사이즈에 대해 : 기본값 10 그대로 유지
image
  • 공식 문서 와 문서 내 영상을 참고
  • 사용중인 인스턴스 코어가 1개이기 때문에 기본설정인 1에서 풀 사이즈를 수정할 필요를 느끼지 못했음.
  • 실제 부하 테스트 결과, 최대 풀 사이즈를 100으로 늘리더라도, 성능 차이가 없었고, 커넥션을 최대 40개까지만 생성함

  1. 그외 설정에 대해 : 권장값 그대로 사용
  • Statement의 캐싱에 대한 설정이 대부분.
  • Hikari가 기본값에서 설정 변경을 권장하는 이유를 추측해보면 다음과 같다.
    • 초기에 설정됐던 기본값 보다는 더 넉넉하게 설정을 줄 수 있을 만큼 하드웨어가 발전함
    • MySQL 버전이 업데이트되며 서버 사이드 캐싱이 가능해짐
  • Statement 캐싱 사이즈를 늘리고, 캐싱을 활성화해주는 옵션들. 권장 값 그대로 사용함.
dataSource.cachePrepStmts=true
dataSource.prepStmtCacheSize=250
dataSource.prepStmtCacheSqlLimit=2048
dataSource.useServerPrepStmts=true
dataSource.useLocalSessionState=true
dataSource.rewriteBatchedStatements=true
dataSource.cacheResultSetMetadata=true
dataSource.cacheServerConfiguration=true
dataSource.elideSetAutoCommits=true
dataSource.maintainTimeStats=false



무중단 배포를 구현하고 배포 과정을 발표한다

  • 서비스를 배포하는 중간에도 사용자는 서비스를 계속해서 사용할 수 있어야 한다

구현 과정

  • 아이디어 정리

    • 이중화를 하지 않았기에 블루 그린 배포로 간단히 구현하기로 선택
    • A, B 포트 두개를 오가며 사용하기로 결정
    • 현재 배포된 포트가 A인지 B인지 식별 후 현재 배포되어 있지 않은 포트를 신규 배포 대상 포트로 설정
    • 신규 배포 대상 포트에 실행중인 프로세스가 있을 경우 kill 수행
    • Jenkins를 통해 전달받은 jar 파일을 신규 배포 대상 포트에 백그라운드 프로세스로 실행
    • 20초 대기 후 actuator health check 엔드포인트로 요청을 보낸 후 status:UP 상태 확인 및 실패 시 프로세스 중단
    • Nginx 설정 수정 및 reload
    • 기존 배포 대상 포트 프로세스 종료
  • 실제 구현

    • 쉘 스크립트에서 조건문, 변수 생성 및 값 할당, 변수 재사용 방법 학습
      • A, B 포트 식별 및 변수 생성 및 할당, 배포 대상 포트에 프로세스 실행중일 경우 종료 처리
    • 기존 배포에서 사용하던 nohup 문법으로 실행. sleep 문법을 통해 배포 대기
    • curl -s 명령을 통해 헬스체크한 결과를 변수에 할당 및 status:UP과 응답 문자열이 일치하는지 확인
      • 일치하지 않을 경우 배포 프로세스를 중단해야 했는데, exit 문장을 사용할 경우 클라이언트가 종료되는 이슈 발생
      • early return 을 위해 함수로 선언하여 사용하도록 개선
    • Nginx의 reload 기능을 이용해 restart 없이 proxy_pass 설정을 변경할 수 있음을 이용하기로 결정
      • 동적 변경을 위해 proxy_pass 를 변수처리 후, 변수와 값을 담은 파일을 외부에서 include 하도록 nginx 설정 파일 수정
      • WAS 서버에서 해당 설정을 담은 파일을 생성한 후, scp를 통해 Nginx 서버로 전송하여 include 될 파일 덮어쓰기 처리
      • ssh 명령을 통해 reload 호출
    • 여기까지 성공되었을 경우, 기존 배포 포트 종료
  • 무중단 검증 및 가용성 측정

image image
  • 개발 서버 배포 프로세스를 실행시킨 후, Jmeter를 이용해 초당 10번의 요청을 전송 테스트
  • 약 1400건의 요청 중, 2건이 정상 응답에 실패함
  • 초당 10번에서 2건이니, 크게 잡아도 0.5초 정도 다운타임으로 가정
  • 1주일에 한 번 배포한다고 가정했을 때, 1년에 다운타임이 30초 미만이므로 six nine, 99.9999% 가용성으로 판정



1,000만명이 사용해도 서비스할 수 있도록 팀의 인프라 아키텍처 개선 방향을 고민한다 (구현 X)

전제


1백 명 이하 사용자 : WAS & DB 분리, 서브넷 분리


image

  • 초기 개발을 마치고 서비스를 시작하는 시점
  • 목표
    • 높은 성능 보다는 비용 효율적일 것
    • WAS, DB 서버의 분리
    • 기본적인 보안
    • 기본적인 모니터링
  • EC2 인스턴스 선택
    • 과도하게 높은 성능을 선택하면 초기 비용 부담이 커짐
    • 지나치게 낮은 성능을 선택하면 비용은 아끼지만 비즈니스 어려울 수 있음
    • 적절한 성능의 인스턴스를 선택하되, 추후 변경 가능한 점 참고.
  • Route 53
    • AWS의 DNS 서비스
    • Public IP를 AWS VPC 내 인스턴스와 연결해준다
  • 서브넷 Public/Private 분리
    • 사용자가 접근해야하는 서브넷과 아닌 서브넷을 분리함
    • WAS는 퍼블릭 서브넷, DB는 프라이빗 서브넷
  • AWS Shield 를 통해 DDos 방어
  • CloudWatch 로 모니터링 및 AWS SNS를 이용한 알람 구성



1천 명 이상의 사용자 : ELB + WAS 이중화 + Managed DB 이중화


image

  • 아직 소규모 서비스이지만, 이제부터는 트래픽 증가를 대비해야 한다
  • 목표
    • AWS 로드밸런서 + WAS 이중화
    • DB 이중화
    • Managed DB 사용 (인스턴스에 직접 설치한 MySQL이 아닌, AWS Managed DB)
  • 다중 가용 영역 활용
    • AWS 하나의 리전에는 최소 2개 이상의 가용 영역이 존재한다.
    • 가령 서울 리전에는 4개의 가용 영역이 존재한다.
    • AWS 로드밸런서를 통해 이중화를 할 때, 아예 다른 가용 영역에 WAS를 추가하는 것이다
  • ELB를 이용한 수평적 확장
    • 안정성을 위해 WAS를 이중화하려면, 이를 앞에서 분배해주는 역할을 누군가 해줘야함
    • AWS의 ELB가 이를 해줌. Elastic Load Balancer
    • 서울 리전 내 A 가용영역에 WAS하나, B 가용영역에 WAS하나를 구성하고, ELB가 서로 다른 가용영역에 있는 WAS 둘에 부하를 분산해줌
  • Managed DB로 전환
    • EC2에 설치된 데이터베이스가 아닌 AWS가 관리해주는 DB서비스 이용
    • 관리 포인트 ⤵️
    • 확장성, 가용성, 내구성, 성능 ⤴️
    • 읽기/쓰기 분리
    • RDS 유형 중 Amazon Aurora 소개
      • MySQL, PostgreSQL과 호환
      • 내부 튜닝을 통해 더 높은 성능을 보인다고 함
      • 3개 가용영역, 6벌 복제, 최대 15개 복제본, 최대 64TB 자동확장



ALB와 NLB


image

  • 큰 범주에서 둘 다 AWS에서 제공하는 ELB 서비스의 일종이다.
  • ALB는 Application Load Balancer
    • L7 기반, HTTP2, HTTPS 지원
    • 소스 IP가 유지되지 않음. 필요시 X-Forwarded-For 같은 헤더 이용해야함
  • NLB는 Network Load Balancer
    • L4 기반, TCP, UDP, TLS 지원
    • ALB와 달리 고정IP 사용 가능



1만 명 이상의 사용자


image

  • 더 이상 소규모가 아님. 중규모 정도는 됨
  • 목표
    • 성능에 본격적으로 신경써야할 시기
    • 인스턴스 증가로 인한 관리 비용이 증가할 시기. 자동화 시작해야.
    • 인스턴스 증가로 인한 비용을 줄일 방법도 필요
    • 보안도 강화해야함
  • Auto Scaling Group을 이용해 성능, 가용성, 비용 효율을 모두 챙김
  • CloudFront, S3를 이용해 정적, 동적 리소스에 대해 캐싱 적용
  • AWS Systems Manager를 이용해 여러 인스턴스 관리 편의성 증대
  • AWS WAF, Shield, GuardDuty 를 이용해 보안 고도화



AWS Auto Scaling Group


image

  • 온 프레미스 환경이라면 피크 트래픽에 맞춰 리소스를 구성해야 한다.
  • 클라우드 환경에선 오토 스케일링을 통해 최적의 리소스를 자동으로 활용 가능.
  • AWS 오토 스케일링
    • 오토 스케일링 그룹에 쓰레드풀, 커넥션풀 만들듯이 최소 최대값을 설정
    • 서버 장애시 최소 수량만큼 자동 복구
    • CloudWatch 지표 기반 스케일링
    • 다른 RDS와 AuroraDB는 DB 인스턴스 자체를 오토 스케일링 가능
      • 다른 RDS들은 스토리지 용량만 오토 스케일링 가능
    • AuroraDB 인스턴스 CPU 메트릭을 기준으로 오토 스케일링 설정 가능



10만 명 이상의 사용자


image

  • 컨테이너 기반 서비스로 전환을 시작해야할 시기

    • 러닝커브가 있어서 처음부터 도입하진 않음
    • 컨테이너는 표준화, 경량화, 이식성, 쉬운 배포로 인해 MSA 필수
    • MySQL : AuroraDB = Kubernetes : EKS(Elastic Kubernetes Service)
  • DB 읽기 성능 개선을 위해 캐싱 적용 필요

  • EKS를 이용해 EC2인스턴스를 대체

  • DB 읽기 성능 개선을 위해 ElasticCache 사용.

    • Cache Miss 일 때에만 DB로 요청 전송



100만 명 이상의 사용자


image image

  • 목표
    • 용도에 맞는 DB 적용
    • 샤딩을 통한 DB 분산
    • 재해복구 (DR) 및 멀티리전 서비스
  • NoSQL 사용하기 - Amazon DynamoDB
    • 장바구니, 위시리스트 처럼 쓰기가 많은 경우 적절
    • 대규모 요청에도 한 자릿수 ms 응답시간
  • 읽기 작업은 ElasticCache → Cash miss 시 DB 또는 DynamoDB
  • 쓰기 작업은 일부 선택한 작업은 DynamoDB에 더 빠르게
  • CDK - Infra as a code
    • 재해 복구를 위해 사용
    • 파이썬, 노드JS, 타입스크립트, 자바 등 언어 사용 가능
    • 인프라, 서비스 구성 자동화 가능
    • 재활용 가능한 템플릿 생성 가능
    • DR 상황에서 복구하도록 구성 가능
  • 데이터 백업
    • S3와 DB에 저장되는 데이터를 다른 리전에 복제시켜둘 수 있음
    • 데이터는 미리 복제 또는 스냅샷을 사용
    • DR 상황에서 구성해두었던 CDK를 이용해 빠르게 복구 구성 가능



1000만 명 이상의 사용자


image image

  • 목표
    • 다중 리전별 서비스를 활성화
  • Aurora 글로벌 DB
    • 여러 리전에 읽기 전용을 구성 (ex. 서울, 런던, 시드니)
    • 단, 쓰기는 한 곳에서만 가능
  • DynamoDB 글로벌 테이블
    • 여러 리전에서 읽기 쓰기 가능
    • 변경이 자동으로 글로벌 리전에 전파됨
  • ElasticCache 글로벌 데이터스토어
    • 읽기 성능 개선을 위해 사용하던 ElasticCache도 글로벌화



결론

  • SPOF 제거를 위한 이중화, Failover, 다중 가용영역, 다중 리전
  • 오토 스케일링
  • 성능, 부하분산을 위해 캐시 사용
  • 모니터링과 보안

필수 요구사항 전체 보기



⚠️ **GitHub.com Fallback** ⚠️