앞장에서 설명한 PersistentDurableStateActor 은 상태있는 서비스에서 분산을 했을때 AKKA를 이용한 분산상태 개발방식입니다.
상태없는 개발방식과 없는 방식의 차이를 먼저알아고보 AKKA의 액터모델이 아닌, 코틀린 순수액터모델을 이용해 유사하게 구현해보고
읽기성능이 얼마나 빨라질수 있는지 확인을 해보겠습니다.
상태없는 서비스 VS 상태 있는서비스 장단점 요약
특성 | 상태없는 서비스 | 상태 있는 서비스 |
---|---|---|
병목 원인 | 데이터베이스, 외부 API, 캐시 사용으로 부하 증가 | 상태 동기화, 세션 관리, 중앙 상태 저장소로 부하 증가 |
확장성 | 수평 확장이 용이하며 병목을 분산 처리 가능 | 상태 동기화 필요로 인해 확장성이 제한됨 |
장애 복구 | 장애 복구가 상대적으로 단순 | 병목 지점의 상태 복구가 복잡 |
최적화 방향 | 요청 간 상태 독립성 활용, 캐싱 및 병목 지점 분산 | 상태 동기화 최적화, 병목 지점 클러스터링 |
적합한 사례 | 대규모 웹 애플리케이션, REST API, 서버리스 설계 | 게임 서버, 채팅, 실시간 세션 기반 시스템 |
일반적인 웹개발에서 상태없는 서비스로 작성하는것이 이득이 있지만 , 게임또는 채팅이 진행되는동안 상태업데이트가 지속 일어나는경우
상태있는 객체를 설계해야할수도 있습니다.
간단한 게임및 비교적 간단한 채팅의 경우 상태없는 서비스로도 충분히 설계가 가능할수 있으며 꼭 어느 한가지방식만 장점이 있을수 있다고 볼수 없으며
다음과 같이 트레이드 오프가 발생할수 있습니다.
상태관리 객체를 만드는 가장 큰 단점은 구현의 난이도에 있습니다.
성능 트레이드오프
장점
- 로컬 상태 관리로 요청 처리 속도가 빨라짐.
- 네트워크 비용 감소와 높은 동시성 처리.
- 읽기와 쓰기의 독립적 최적화.
- 데이터베이스 성능 의존을 줄일수 있음
단점
- 상태 동기화와 장애 복구(예: 인스턴스 장애 시 상태 손실) 복잡성 증가.
- 상태 저장소와 메모리 사용량 증가.
- 서버 장애 시 상태 복구를 위한 이벤트 로그 또는 스냅샷 관리 필요.
액터모델은 기본적으로 상태를 관리하며 라이프 사이클이 웹(REST API)에서 요청하는 사이클보다 긴 사이클의 상태관리를 할때 활용할수 있습니다.
시도되는 코드
- 조건에 따른 상태저장 : 특정 사용자가 Hello를 하면 사용자별 카운트 1증가 , 기분이 나쁜 상태일때는 Hello를 거부 카운트 증가없음
- 상태읽기 : 특정 사용자 Click 카운트를 확인 하기 위해 1000번 조회후 성능측정
- 추가 미션 : 마지막 상태값 저장뿐만 아니라 상태 로그를 저장해 시계열분석이 가능하도록 데이터 처리
성능표
- Total time for 100 Hello commands for Write: 73 ms
- Average time per Hello command for Write: 0.73 ms
- Total time for 1000 HelloCount for Read commands: 75 ms
- Average time per HelloCount command: 0.075 ms
성능표를 먼저 공유하면~ 저장시 마지막 상태는 Redis에 저장을 하고, 로그성은 Kafka에 저장합니다.
해당 객체가 상태를 가지고 있기때문에 읽기시 Redis로부터 값을 읽을 필요없이 로컬에서의 상태값값을 반환합니다.
Redis가 아무리 고성능 장치라고 하지만 1000회조회에 75ms 이내로 수행하기는 어렵습니다. 다음과 같은 결정적인 이유가 있기때문입니다.
- Redis 를 1000번 호출한다는것은 인메모리에서 1000번 호출할것같지만 네트워크 호출 1000회가 포함되어 있습니다.
- 상태없는 프로그래밍에서 최적화 지점은 Redis가 고성능이라고 믿고 있지만 네트워크 호출 횟수조차 줄여~ 단일지점 저장소의 부하를 어플리케이션에 분산하는것에 있습니다.
이것을 모델 다이어그램으로 정리하면 다음과 같이 동작하게 됩니다.