본문 바로가기
Java

Java) 병목현상 해결 과정

by NH_club 2023. 8. 23.

SSE 연결 후에 입찰 요청 성능테스트를 진행하는 과정에서 생긴 문제이다.

HikariCP Time out이 발생했다.

첫 번째 가정: 다른 API에서 물린 Connection이 아직 남아있는 건가?

나는 입찰과 조회를 동시에 트래픽을 발생시키기 위해 입찰과 조회 동시에 요청, 입찰만 요청, 조회만 요청 등등 경우의 수를 테스트 했었다. 그렇다면 입찰 쪽이 아니라 조회 쪽에서 Connection을 차지하고 있을 수도 있겠다는 생각에 RDS를 재부팅하고 입찰만 테스트 해보았다. 처음의 성능 테스트는 잘 이루어 졌지만, 두 번째 테스트 부터 같은 에러가 발생했다.. 서로의 상관관계는 없어보인다.

두 번째 가정: HikariCP에서 생긴 Deadlock?

하나의 Thread가 하나의 Connection을 요청하는지 확인해야 한다.

하나의 Thread가 2개의 커넥션을 요청해야 하는 경우 Connection 한개를 물고 다른 커넥션 하나를 기다리며 교착상태(Deadlock)에 빠질 수 있다. Connection을 두개 이상 필요한 로직이라면 Connection Pool Size 공식에 맞게 Connection pool size를 조정해야 한다.

검증 방식: Connection pool size를 1로 설정하고 요청 보내보기

입찰과 SSE연결 둘 다 Connnection pool size 1로도 모든 요청을 완벽히 수행해낸다.... deadlock은 아닌걸로.........

그럼 뭐지.......뭔데 왜인데!!!!!!!!!!!!!!!

 

Time Out은 왜 발생하나? 모든 Connection pool에 Thread 가 들어가 있고, handOffQueue에서 Connection을 기다리는 Thread들이 default 값인 30초가 지나면 Time Out을 던짐. 그렇다면 Connection pool에 들어간 Thread 들이 30초 이상 머무르고 있다는 것인데…… deadlock이 아니라면 왜일까….

세 번째 가정: 하드웨어 성능 문제

현재 EC2의 인스턴스는 t2.micro이다. 현재 입찰쪽 로직에는 배타락으로 구현했다. 이는 락이 걸린 상태에선 읽기, 쓰기가 불가능하며, 락이 걸리면 다른 요청은 락이 풀릴 때 까지 기다려야 한다. 동일한 코드로 로컬과 RDS, EC2 서버와 RDS의 테스트를 진행해 봤으며 결과는 너무 달랐다.

로컬은 1분에 8000건까지 무리 없이 수행하는 반면, EC2는 1분에 650건도 HikariCP Time Out 발생한다.

문제 원인 발견

1. 나의 로직은 Connection pool에서 한개의 Connection만을 필요로 한다. - deadlock 아님

2. Lock은 나의 로직에서 하나만 사용한다. - 락에서 발생하는 deadlock 아님

3. 하드웨어 성능이 높은 환경에서는 문제가 발생하지 않는다.

4. HikariCP 에서 Connection을 얻고, 처리하는 트랜잭션엔 락이 걸려있다.

5. 서로 다른 Connection을 얻은 트랜잭션들은 다른 Connection의 락이 풀릴 때 까지 기다린다.

    1~10까지의 Connection이 열려있다면, 1개의 Connection이 끝날 때 까지 9개의 Connection은 대기중.

6. 하드웨어 성능이 좋지 않아 Transaction 처리 속도가 느리다.

7. 1~10까지의 Connection 중에서 1개의 Connection 처리를 할 때 까지 9개의 Connection은 대기하면서 요청이 쌓이게 되고, 병목현상이 발생한다.

8. 병목현상이 발생하면서 handOffQueue에서 기다리는 요청들이 많아진다.

9. 결국 30초가 지나 Time Out 발생.

해결 방안
  • 병목현상이 일어나지 않도록 로직을 점검하고, 최적화를 시킨다.
  • Connection pool에 time out 시간을 짧게 설정해서 대기하는 요청시간을 줄인다.
    • 병목현상때문에 몇 십초 동안 입찰요청을 대기 시키는 것보다 짧게 time out 을 설정하고 입찰 재시도를 요청하는 것이 더 나을 것 이라 판단.
  • Scale-up
해결 방안 선정

현재 EC2의 인스턴스 스펙이다. 굉장히 낮다.

프로젝트 마무리까지의 시간이 많이 남아있지 않고, 다른 API에서도 하드웨어 이슈가 발생하고 있기에 Scale-up을 하여 하드웨어 성능을 높이기로 결정했다.

Scale-up 이후 추가 해결

https://nh-club.tistory.com/entry/Spring-Transaction-%EC%B2%98%EB%A6%AC-%EC%86%8D%EB%8F%84-%ED%96%A5%EC%83%81

'Java' 카테고리의 다른 글

Java) 데몬 쓰레드와 사용자 쓰레드  (0) 2023.09.18
Java) 프로세스와 쓰레드  (0) 2023.09.14
JMeter 변수 설정  (0) 2023.08.15
JMeter 성능 테스트  (0) 2023.08.15
Java) Faker를 통한 더미데이터 생성  (0) 2023.08.11