0. 배경
웹소켓을 이용하여 실시간 매칭 시스템을 구현하고 동시에 여러 사용자가 접근하는 테스트를 하는 여러 에러를 겪었고, 서비스에 큰 문제가 생길 수 있기 때문에 해결하는 과정을 정리하였습니다.
1. 동시성 문제가 어떻게 발생할까
동시성 문제가 발생하는 상황을 시뮬레이션 해보겠습니다. 이 상황에서 여자 1명이 대기 중이고, 남자 2명이 동시에 웹소켓 매칭 시스템에 접속하면 어떤 문제가 발생할 수 있는지 설명하겠습니다.
1.1 상황 설정
1. 여자 사용자 A가 매칭 대기 중
2. 남자 사용자 B, C가 동시에 웹소켓 매칭 시스템에 접속
3. 시스템은 1:1 매칭을 해야 한다.
1.2 동시성 문제 시나리오
대기 상태 [A]이며 B, C가 동시에 매칭 요청을 보냅니다.
사용자 B의 매칭 요청 처리 -> A를 선택하여 B와 매칭을 시도합니다.
사용자 C의 매칭 요청 처리 -> A와 B는 매칭이 되었기 때문에 다른 사용자가 접속할 때 까지 대기합니다.
동시성 문제 발생 가능성
여기서 동시성 문제가 발생할 수 있습니다.
만약 B, C가 거의 동시에 매칭 요청을 보냈고, 시스템이 동시성을 제대로 처리하지 못한다면 어떻게 될까요?
사용자 B와 C는 사용자 A와 매칭되려고 시도할 수 있고 이 경우 A는 동시에 두 명과 매칭된 상태가 됩니다.
1.3 Jmeter를 이용하여 동시성 시나리오 설정
1번 남자와 2번 남자가 동시에 매칭 시스템에 접속하는 시나리오입니다.
매칭 시스템에서 대기 중인 사람이 존재하고, 1번 남자 2번 남자가 동시에 접근하였을 때 어떤 상황이 발생하는지 알아보겠습니다.
2. [TEXT_PARTIAL_WRITING] 문제 발생
먼저 발생 지점을 살펴보겠습니다.
2.1 발생 지점과 원인
매칭이 되었을 때, 사용자에게 상대방 정보를 제공합니다.
sendMessage를 통하여 서로의 정보를 제공하는 과정에서 문제가 발생합니다.
여러 스레드나 비동기 함수가 동시에 같은 웹소켓 연결에 접근하여 메세지를 보내려고 할 때 이런 문제가 발생합니다.
위에 상황을 연결시키면 A와 B는 서로에게 sendMessage를 통하여 정보를 전달하는 과정에서 A와 C도 sendMessage에 동시에 접근하여 발생한 문제입니다.
2.2 해결 방법
저는 이러한 동시성 문제를 해결하기 위해 매칭 로직에 동기화 메커니즘을 도입하였습니다.
Java의 synchronized를 이용하여 동시 접근을 막아 해결하였습니다.
TEXT_PARTIAL_WRITING에 대한 문제는 해결하였지만, 맨처음 시나리오에서 예상했던 동시성 문제가 발생하였습니다.
3. 동시성 문제 발생
동시성 문제가 발생하였을 때 어떻게 되는지 확인해보겠습니다.
원래라면, 먼저 접속한 1번 유저랑만 매칭이 되어야 하지만 동시성 문제로 인하여 2명과 매칭이 된 상황입니다.
3.1 synchronized를 사용하였는데 왜 발생할까?
Java의 synchronized는 여러 유형의 블록에 사용될 수 있습니다.
저는 현재 메소드 안의 동기화 블록을 만들어서 사용하였기 때문에 sendMessage에 대한 동기화만 처리할 수 있고 메소드 자체 동기화 처리가 된 것이 아니기 때문에 문제가 발생하였습니다.
이러한 문제를 해결하기 위해서 메소드를 동기화하여 해결하였습니다.
3.2 메소드를 동기화하여 해결
메소드를 동기화 하여 동시에 여러 사용자와 매칭이 되는 상황을 막았습니다.
4. 결론
synchronized를 이용하여 동시성 문제를 해결할 수 있었습니다.
여러가지 방법이 존재하지만 이러한 방식을 적용한 이유는
1.직관적이고 간편하기 때문에 이러한 방식을 적용하였습니다.
2.단일 서버 환경이기 때문에 적용할 수 있습니다.
3.매칭 시스템이 오래 걸리지 않기 때문에 사용자가 많아도 충분하다고 판단되어 적용하였습니다.
동기화 방식을 사용하였을 때 발생할 수 있는 문제점에 대해서는 다음 포스팅에서 알아보겠습니다.
'Spring' 카테고리의 다른 글
Spring Security - Swagger 적용하기 (0) | 2024.09.18 |
---|---|
Scale-out 상황, 채팅 서비스 Redis 도입 (0) | 2024.06.20 |
좌표값(객체) 테스트에 대한 고민 (0) | 2023.11.25 |
테스트 코드 - Presentation Layer (0) | 2023.11.12 |
CSRF(Cross-Site Request Forgery)란? (1) | 2023.10.19 |