Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4.5주차 과제] 챌린지 과제 #16

Open
choyeongju opened this issue Nov 8, 2024 · 0 comments
Open

[4.5주차 과제] 챌린지 과제 #16

choyeongju opened this issue Nov 8, 2024 · 0 comments
Assignees

Comments

@choyeongju
Copy link
Member

choyeongju commented Nov 8, 2024

✅ Spring Boot Application 은 DB 와 연결을 언제 맺을까요?

DB 도 서버와 통신하는 서버라고 이야기했는데요,

  1. 그럼 그 연결은 언제 맺고
  2. 요청은 언제,
  3. 그리고 어떻게 보내게 될까요?

 

🔑 DBCP(Database Connection Pool)

🔑 HikariCP

 

🍪 DB 연결은 언제 맺어지나요?

DB connection : Backend server 와 DB 서버 사이의 연결

  • Application Context 가 초기화될 때 !!
    • Application Context 는 별도의 설정 정보(ex @configuration 이 적용된 클래스) 를 참고하고 IoC 를 적용하여 빈의 생성, 관계 설정 등의 제어 작업을 총괄합니다.
  • 이때, DataSource 객체를 통해 DBCP(Database Connection Pool)가 생성됩니다.
  • Spring Boot는 기본적으로 HikariCP라는 커넥션 풀 라이브러리를 사용합니다
    • 애플리케이션이 실행될 때, 미리 일정 수의 데이터베이스 커넥션을 생성, 필요에 따라 커넥션을 가져오고 반환하는 방식으로 동작합니다.

 

🍪 API 요청 흐름

백엔드 서버에서 API 요청을 DB 서버로 보내는 과정의 통신은 TCP(연결지향적) 기반으로 동작 합니다.

이 과정에서 connection 을 열고, 닫는 과정에서 꽤 많은 시간이 소요됩니다. ( 3 way, 4 way handshaking)

 

🍪 DBCP 등장 배경

위의 시간적인 비용 때문에 API 응답이 늦어지는 문제점.. 을 해결하기 위해 등장!

 

  1. API 요청을 받게 되면
  2. connection pool 에서 놀고 있는 connection 을 데려와서 이를 바탕으로 쿼리를 보냅니다.
  3. 쿼리 요청, 응답 후 close connection 하게 되면
  4. connection pool 에다가 다시 connection 을 반환합니다.

 

즉, 본격적으로 API 요청을 맺기 전에

요청이 있을 때마다 새로운 커넥션을 생성하는 것이 아니라

백엔드 서버와 DB 서버 간에 DB connection 을 미리 만들어놓고,

재사용함으로써 연결을 open 하고 close 하는 시간을 절약합니다.

 

⇒ 이 Pool 을 DBCP(Database Connection Pool) 라고 부릅니다!

🍑 DB서버 설정 (Mysql 을 가정)

클라이언트는 DB 서버에 요청을 보내는 모든 것들 즉, 여기서는 백엔드 서버가 될 수 있습니다.

중요한 파라미터 2가지를 살펴볼까요?

 

  • max_connections
    • 클라이언트와 DB 서버가 동시에 맺을 수 있는 최대 connection 수
  • wait_timeout
    • 백엔드 서버가 생성한 connection 이 일정 시간 동안 아무 작업도 하지 않을 경우, 자동으로 종료시키기 위해 설정한 시간

 

💡 만약, max_connections 랑 DBCP conection 이 모두 4라면 ?

DB서버 입장에서는, 이미 MAX 만큼 connection 을 맺고 있는 상태가 됩니다.

여기서 만약 백엔드 서버가 바쁘면 connection 들이 바쁘게 사용되는데… 그래서 ‘서버를 한 대 더 도입하자’ 는 의견이 나왔다??! 근데 DB 서버는 이미 connection 을 최대로 맺고 있어서 새로 투입된 백엔드 애플리케이션은 연결을 맺을 수 없습니다!!

→ max_connections 값을 충분히 잘 설정해 주어야 새로운 서버를 투입해도, 에러 없이 정상 작동하게 됩니다.

 

🍑 DBCP 서버 설정 (HikariCP 을 가정)

[공식문서]

https://github.com/brettwooldridge/HikariCP

 

  • minimumIdle : pool 에서 유지하는 최소한의 idle(유휴) connection 수
  • maximumPoolSize : pool이 가질 수 있는 최대 connection 수
    • idle + active 합쳐서 최대 수
  • maxLifeTime : pool에서 각 connection의 최대 수명
  • connectionTimeout : 애플리케이션이 CP로부터 connection 을 얻기 위해 대기할 최대 시간

 

💡 만약, DBCP size 가 4개로 고정이었다 ?

4개에서 3개로 connection 하나가 사라져도 바로 새로 1개를 생성해서 다시 4개로 유지합니다.

connection을 pool 로 반환하지 않으면 사용되고 있는 connection으로 간주되어 maxLifetime 이 동작 하지 않게 됩니다.

connection 이 반환되지 않으면 사용 가능한 connection 이 부족해지고, 추가 요청이 들어오면 connectionTimeout이 발생할 수 있기 때문에, 다 쓴 connection은 pool로 반환을 잘 시켜주는 것이 중요합니다!

image

데이터베이스나 인프라에서 부과하는 connection time limit 보다 몇 초 더 짧아야 합니다. ”

 

⇒ 이런 파라미터들을 적절하게 설정하는 것이 중요 !

 


✅ 그렇다면 디폴트로 맺어지는 연결의 수는 얼마고, 어떤 수가 적정할까요?

🍪 디폴트로 맺어지는 연결의 수는요?

image

별도의 설정을 하지 않으면 HikariCP는 기본적으로 최대 10개의 DB connection 을 관리합니다.

 

HikariCP 에서 권장하기를..

image

  • minimumidle의 기본값은 maximumPoolSize 와 동일한데,
    minimumidle 값을 별도로 설정하지 말고 maximumPoolSize와 동일하게 유지하는 것을 권장합니다.
  • 즉, Connection Pool 의 사이즈가 고정이라는 의미입니다.

 

왜 그렇게 해용?

💡  minimumidle < maximumPoolSize 라고 생각해볼까?

추가 트래픽이 몰릴 때마다 connection 을 만들어주어야 하는데, 아까 살펴보았던 것처럼 connection 을 만드는 과정은 시간이 많이 듭니다. connection 을 만들어 주는 속도보다, 더 빠른 속도로 트래픽이 몰려오게 되면 백엔드 서버의 응답이 느려질 수 있습니다.

⇒ 애초에 처음부터 적절한 개수로 Connection Pool size를 고정해서 사용하라! 는 말

⇒ 왜냐? 트래픽이 급증해도 새로운 connection 생성하느라 시간낭비 안하고 즉각 대응이 가능하니까!

 

🍪 그렇다면 적정한 connection 수는요?

딱 정해져 있는 정답은 없다 !!!
: 모니터링 & 부하 테스트 를 통해…..

1️⃣ 모니터링 환경을 구축

CPU, 메모리, 서버 스레드 수, DBCP 상태 등을 파악한다.

 
2️⃣ 부하 테스트 진행

request per second(백엔드 시스템의 전체적인 처리량) & avg response time(API 성능확인)을 확인

  • request per second : 트래픽 늘어나다가 어느 순간에는.. RPS가 일정하게 유지, avg response time또한 일정하게 유지되다가 계속 증가.

    → 이 유지, 증가 되는 병목 포인트들에서 지표들이 어떻게 되는지 모니터링 해야겠다!

 
3️⃣ 백엔드 서버 & DB 서버의 등의 리소스(CPU, MEM) 사용률 확인

  • 백엔드 서버의 리소스 사용률 많으면 많으면 백엔드 서버 추가!

  • DB서버의 리소스 사용률 많으면.. 부하 낮추는 방법 여러가지 존재함 (생략)

    → But, 둘 다 괜찮은데 병목 포인트가 생기면??

 
4️⃣ 추가적인 지표 확인 1

  1. thread per request(요청당 하나의 스레드를 사용) 모델이라면 → active thread 수 확인 → 괜찮은데?
  2. 그럼 DBCP의 active connection 수 확인 → 헉 이게 문제였군.
  3. maximumPoolSize 를 올려가면서 다시 부하 테스트

⇒ 근데, connection pool 사이즈를 늘려도 어느 순간부터 성능이 개선이 안된다면??

 
5️⃣ 추가적인 지표 확인 2

  • DB 서버의 max_connections 의 수 확인해서 필요하면 늘린다!

⇒ 사용할 백엔드 서버 수(CPU등등)를 전체적으로 고려하여 DBCP의 max pool size 결정

⇒ 종합적으로 고려하면서 적절한 DB의 connection 수 설정

 
요약

  1. DB의 max_connections 수 확인 → 필요 시 조정
  2. 그를 기준으로 백엔드 서버 수를 고려해서
  3. max_connections 초과하지 않도록 각 서버의 DBCP 별로 max pool size를 어떻게 가질건지 설정

 
여러 종류의 DBCP가 존재함! HikariCP, Apache Commons DBCP..

자기가 쓰는 DBCP 를 잘 숙지하는 것이 중요함~

 
(+) 네이버에서 쓴 Commons DBCP

https://d2.naver.com/helloworld/5102792

@choyeongju choyeongju self-assigned this Nov 8, 2024
@choyeongju choyeongju changed the title [4주차 과제] 서버 인프라 [4.5주차 과제] 챌린지 과제 Nov 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant