728x90

세션 풀림 문제 중 가장 중요한 것 하나는 Android Side - Back-end Side - Godomall 로 이어지는 연계순서였다.

중간에 이 과정에서 Spring 에서 "Bearer " 에 대한 String 을 떼어버리고 파싱한 뒤에 Godomall 쪽에 이어지는 순서로 접근하게 되는데, 이 과정에서 다시 한 번 Session Connection 이 이루어질 수 있었다.

 

자 그러면 본론으로 돌아가서 왜 한번의 Session 발급 이후에 Session 이 풀리고나서 로그인하기 힘들었던 이유가 있었는지 생각해보자

 

 

1. 

Moyamo Android Side run - init - Shop request 

이 순서상에서 이루어질 때, 앱을 처음 실행한 사용자라던가 캐시가 없는 사용자라면 해당하는 부분에 대해서 다시금 Session Sync 가 이루어졌어야 하기 때문에 한번의 연결은 정상적으로 작동하게 된다.

 

다만 그 이후에 refresh Token 이라던지 access Token 이 들어왔을 때에 주기적으로 돌아야 하는게 없었기 때문이다.

- 물론 이 부분에 대해서 찾아보면 refresh Token 이나 access Token 에 대한 로직이 있을지라도 활성 사용자수인 25만명에비하여 실사용자는 5~7만명에 그칠 것이기에 데이터베이스에서 직접 긁어다가 작동시키는 부분은 생각보다 비효율적인 트래픽을 야기할 수 있다.

 

2.

그렇다면 어차피 끊긴 김에 User의 Shop Profile 을 확인하는 End-Point 를 호출해서 소환하는 구조로 간다.

- 이 경우 Android 사이드에서 앱이 켜질때마다 request 를 날려주는 번거로움이 있긴 하지만 적어도 Session 에 대한 안정성은 보장할 수 있다. 따라서 Web-View 상에서 불러오는 쿠키의 Session 에 대해서도 변함없이 사용자가 서비스를 지속적으로 이용하게 해줄 수 있다.

 

따라서 이번엔 2번으로 접근하는 것을 유도해보고, 1번은 별도의 분석에 들어가기로 했다.

728x90

발생했던 Shop 에서의 Session 동기화 문제를 정상적으로 수정했다.

 

 

일단 내가그린기림기르김그림 을 기반으로 설명해보자면

결과적으로 예전에 China Developer 에 의해서 Credential Key가 노출되서 이 부분에 대해서 변경하고 재배포 하는 과정에서 Scheduler 를 가동할 수 있는 곳이 따로 있었던 곳을 발견했다.

 

 

즉  tools 인스턴스 안에서도 가능하고, scheduler 인스턴스 안에서도 가능했던 것이다

 

 

문제 1. Ranking Serviece 및 Score 부분에서 2번 집계되는 현상 발생

자 이 부분에서 해결하기 위해서, scheduler 인스턴스 내에서 관리할 수 있도록 해당 부분에서 daemon을 activate시키고

tools 에 있던 scheduler 는 deactivate 시키는 것을 했었다. 

 

그 이후에 참조를 이루는 부분에서 scheduler 에 있는 부분에서 sync 가 정상적으로 이루어지지 않았으니

tools 에 기반하는 scheduler 에서 정상적으로 작동할 수 있냐는 의문을 가졌던 것이다.

 

그렇게 판단한 기반 근거를 살펴보자

1. scheduler 내에서 사용되던 log 가 2020 ~ 2021년 사이에는 존재했으나, 그 이후에는 로그 기록이 확보되지 않았다. 물론 이러한 부분에서 log rotate 가 작동된 것일 수 있겠으나, 이러한 부분에서 deprecated 됬었을 수 있다는 것을 추론 할 수있다.

 

2. tools 내의 scheduler 에서 가동되던 log를 살펴보면 2022년 6월 22일 정도를 마지막으로 이루어졌다가 이후 약 2~3개월의 Gap 이 있다가 다시 3월까지 이루어졌었다.

 

이러한 부분에 의하여 Scheduler 가 고도몰의 Custom Session Method 를 연결하여 지속적으로 연결을 성립하는 역할을 한다면, 충분히 참조될 만 하다는 것이다.

 

그렇다면 여기서 놓치고 있는 것이 무엇이였을까?

 

추측 가능한 결론

1. 아마도 EIP 에 의해서 Static IP가 주어지고, 해당하는 부분에 의해서 지속적으로 연결을 수립하여 생기는 과정 중에 tools 에 고정해놨을 반면에 scheduler 에서는 EIP 가 배정되지 않았던 것과 동시에 별도의 IP가 존재하는 부분

 

하지만 이러한 부분에서 약간의 추론을 더 생각해보자면, 내부적으로 ELB를 호출해서 rest 쪽을 호출했었고, 이러한 부분에 의하여 rest의 End-Point 를 호출하기 때문에 별도의 Scheduler 에 의한 부분을 찾지 못했던 것이다.

 

 

추가적으로 찾아봐야 할 것

샵에서 로그인이 풀리는 이슈나 종종 로그인 세션이 잡히기는 하지만 풀리는 이슈에 대해서 완전히 해결되긴 하였다.

 

하지만, tools 에 관련된 부분을 참조하여 지속적으로 이루는 부분이 있는지 확인사살을 해야할 것 같다. 아마 분명히 있을 것이라 본다.

 

 

728x90

AWS Instance 내에서 기본적으로 보여지는 2가지의 Duplicated 된 것이 보였는데,

moyamo-scheduler 

그리고 moyamo-tools 내에서 운영되는 scheduler 가 중첩되었었다.

 

이러한 부분에서 두 가지의 scheduler 가 다른 역할을 하냐고 물어본다면, 역시나 아니다.

한 가지의 scheduler 는 분명히 suspend 되거나 terminated 되었어야 할 것 같은데, 내부 Log상으로 봐서 예전에 쌓여있던 로그 자체에서도 moyamo-scheduler 는 2021년에 사용하던 기록에서 유래된 것이고, 이러한 부분들은 확실히 ELS와 기타 다른 module 들이 합쳐진 곳에서 운영되는 scheduler 와는 별도로 관리되었던 것이다.

 

여하튼 2개를 같이 키면 당연히 scheduler가 2번 수집하게 되므로, Record 도 2번 쌓이게 되는데

그렇다면 발생하는 문제는

 

랭킹 Score 에서 2배로 쌓이는 것

그리고 해당하는 부분에 있어서 Score 가 문제가 아닌 댓글 Counting 에 대해서도 2배가 되는 현상이 발견되었었고

 

이 때문에 해당하는 부분에 대하여 해결하기 위하여 예전에는 moyamo-scheduler 내에서만 daemon을 가동시키고

tools에서는 종료를 시켰었다.

 

하지만 관리 포인트의 증가와 동시에 Tools 에서 참조하는 문제가 뭔가가 벌어졌어지리라고는 생각하지 못했는데,

공교롭게도 전 개발사에 의하여 Credential Key가 노출되는 상황이 벌어졌었고, 그 때문에 Credential key를 교체하는 상황에서 해당하는 부분에 대하여 내가 인지하지 못했었다.

 

그 이후에 Credential Key를 교체하고 전부 jar 로 컴파일하여 정상적인 모듈로 탑재하였으나, 모야모 샵 내에서 고도몰 세션 이슈가 발생했었는데.. 아무리 코드를 분석해봐도 예전에는 정상적으로 작동되던 것이 어떤 부분때문에 문제가 되는지 정말 어리둥절 하기도 했고

 

그 때문에 Spring - Android - Godomall 사이에서 오가는 Log를 수집하면서 accessToken 에 대한 byte 길이의 차이라던가 그런 부분에 대하여 파악하기도 하였고

 

Godomall 내부에서 overwritten 된 Custom Session Code에 대하여 전부 분석해보았으나, 에러찾기는 굉장히 애매한 상태인 것이다.

 

고렇다면 문제가 무엇일까

1. 

아마 예상컨데 Session 을 주기적으로 연결하고 끊는 과정에서 생기는 어느정도의 간헐적인 Delay 이슈일 수도 있을 것

 

2.

그리고 Android 에서 Spring 쪽을 호출하고, Spring 쪽에서 호출하는 뭔가 메세지 브로커 같은 것이 정상적으로 관리가 안되고 있을 가능성

 

3. 

망할놈의 Hikari CP 안에서 정상적으로 데이터베이스에 대해서 놓고 빼고 놓고 빼고를 하지 못할 가능성

그렇다고 해서 커넥션 풀을 최적화 하는걸 배제하고 read, write instance 에 대해서 증가시키는 것은 좀 에바참치니까 일단 풀부터 조져봐야한다

 

4.

고도몰 내에서 작성된 Custom Session 코드와 Spring 쪽에서의 통신 문제 - 근데 이건 다 살펴봐서 패스

 

5.

Android 측면에서 발견될 문제로 생각될 수도 있는데, 이건 Yagnesh 가 아무리 생각해도 Back-end Issue 라고 하니까 뭐 어케든 처리해야것다

728x90

실무환경에서 DataBase 성능 최적화 및 ORM에 대해 이야기 할때 커넥션풀이라는 단어가 자주 등장하여 한번 정리가 필요할 것 같아 정리한 포스트 입니다.

🍌 JDBC란?

Hikari CP(히카리 커넥션풀)을 알아보기에 앞서 JDBC의 개념을 정리하자면,
JDBC는 Java Database Connectivity의 약자로 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API다.

JDBC는 데이터베이스에서 자료를 쿼리하거나 업데이트하는 방법을 제공한다.


🍑 DB 커넥션 풀이란

일반적인 데이터 연동과정은 웹 어플리케이션이 필요할 때마다 데이터베이스에 연결하여 작업하는 방식입니다.
하지만 이런 식으로 필요할 때마다 연동해서 작업할 경우 데이터베이스 연결에 시간이 많이 걸리는 문제가 발생합니다.

예를들어 거래소의 경우, 동시에 몇천명이 동시에 거래 및 조회 기능을 사용하는데 매번 데이터베이스와 커넥션을 맺고 푸는 작업을 한다면 굉장히 비효율적일 것입니다.

이 문제를 해결하기 위해 현재는 웹 어플리케이션이 실행됨과 동시에 연동할 데이터베이스와의 연결을 미리 설정해 둡니다.

그리고 필요할 때마다 미리 연결해 놓은 상태를 이용해 빠르게 데이터베이스와 연동하여 작업을 합니다.

이렇게 미리 데이터베이스와 연결시킨 상태를 유지하는 기술을 커넥션 풀
(Connection Pool, CP)라고 합니다.


🍊 스프링에서의 커넥션 풀

자바에서는 기본적으로 DataSource 인터페이스를 사용하여 커넥션풀을 관리한다.

Spring에서는 사용자가 직접 커넥션을 관리할 필요없이 자동화된 기법들을 제공하는데

SpringBoot 2.0 이전에는 tomcat-jdbc를 사용하다,
현재 2.0이후 부터는 HikariCP를 기본옵션으로 채택 하고있다.


🍓 왜 Hikari Cp일까?

히카리 벤치마킹 페이지를 참고하면 아래와 같이 월등한 성능을 보인다는 것을 알 수있다.


HikariCp가 다른 커넥션풀 관리 프레임워크보다 빠른 성능을 보여주는 이유는
커넥션풀의 관리 방법에 있다.

히카리는 Connection 객체를 한번 Wrappring한 PoolEntry로 Connection을 관리하며,
이를 관리하는 ConcurrentBag이라는 구조체를 사용하고 있다.

ConcurrentBag은 HikariPool.getConnection() -> ConcurrentBag.borrow()라는 메서드를 통해 사용 가능한(idle) Connection을 리턴하도록 되어있다.

이 과정에서 커넥션생성을 요청한 스레드의 정보를 저장해두고 다음에 접근시 저장된 정보를 이용해 빠르게 반환을 해준다.

이러한 방법 때문에 속도에 이점이 있으며 해당 방법의 자세한 설명은 아래 블로그를 참조하면 좋을 것 같다.
HikariCP Dead lock에서 벗어나기 (이론편)


🍎 Hikari CP 사용법

build.gradle에 따로 추가할 필요 없이
"org.springframework.boot:spring-boot-starter-jdbc"
를 추가하면 자동으로 추가된다.

이후 application.yml에 설정값을 추가하면 되는데

spring:
 datasource:
   url: jdbc:mysql://localhost:3306/world?serverTimeZone=UTC&CharacterEncoding=UTF-8
   username: root
   password: your_password
   hikari:
     maximum-pool-size: 10
     connection-timeout: 5000
     connection-init-sql: SELECT 1
     validation-timeout: 2000
     minimum-idle: 10
     idle-timeout: 600000
     max-lifetime: 1800000

server:
 port: 8000

options

  • maximum-pool-size: 최대 pool size (defailt 10)
  • connection-timeout: (말 그대로)
  • connection-init-sql: SELECT 1
  • validation-timeout: 2000
  • minimum-idle: 연결 풀에서 HikariCP가 유지 관리하는 최소 유휴 연결 수
  • idle-timeout: 연결을위한 최대 유휴 시간
  • max-lifetime: 닫힌 후 pool 에있는 connection의 최대 수명 (ms)입니다.
  • auto-commit: auto commit 여부 (default true)

🍋 DeadLock 피하기

이론적으로 필요한 최소한의 커넥션 풀 사이즈를 알아보면 다음과 같다.

PoolSize = Tn × ( Cm -1 ) + 1

  • Tn : 전체 Thread 갯수
  • Cm : 하나의 Task에서 동시에 필요한 Connection 수

위와 같은 식으로 설정을 한다면 데드락을 피할 수는 있겠지만 여유 커넥션풀이 하나 뿐이라 성능상 좋지 못하다.
따라서 커넥션풀의 여유를 주기위해 아래와 같은 식을 사용하는것을 권장한다.

PoolSize = Tn × ( Cm - 1 ) + ( Tn / 2 )

  • thread count : 16
  • simultaneous connection count : 2
  • pool size : 16 * ( 2 – 1 ) + (16 / 2) = 24

더 자세히 알아보고 싶으면 다음 블로그에서 확인하면 좋을듯 하다.
HikariCP Dead lock에서 벗어나기 (실전편)

 

https://velog.io/@miot2j/Spring-DB%EC%BB%A4%EB%84%A5%EC%85%98%ED%92%80%EA%B3%BC-Hikari-CP-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0

 

[Spring] DB커넥션풀과 Hikari CP 알아보기

실무환경에서 DataBase 성능 최적화 및 ORM에 대해 이야기 할때 커넥션풀이라는 단어가 자주 등장하여 한번 정리가 필요할 것 같아 정리한 포스트 입니다.

velog.io

 

+ Recent posts