글
지금까지 작성한 글들을 모아봤습니다.
-
왜 인스턴스를 두 개로 늘릴 수 없는가 — 인메모리 pool의 수평 확장 한계
reputation-pool-cloud의 인스턴스를 두 개로 늘리면 같은 리소스가 중복 대여되고, JVM별 fencing token이 충돌하며, 전체 snapshot checkpoint가 서로의 변경을 덮어쓸 수 있습니다. 아직 운영 장애가 아니라 현재 코드에서 구성한 설계 반례입니다. lease·snapshot·메모리 예산·rate limit의 정확성 범위를 추적하고 tenant sharding, 상태 외부화, single writer를 비교해 다음 경계를 결정합니다.
-
데이터를 나눴는데 장애는 함께 났다 — 멀티테넌트 격리와 noisy neighbor 대응
reputation-pool-cloud에서 API key를 tenant로 해석하고, tenant별 ResourcePool·PostgreSQL row·이벤트 스트림을 격리한 과정을 다룹니다. 데이터가 섞이지 않는 것만으로는 충분하지 않았습니다. 모든 tenant가 한 JVM의 heap과 처리량을 공유했기 때문에 한 tenant의 리소스 폭증과 요청 폭주가 전체 장애로 이어질 수 있었습니다. 전역 메모리 예산, tenant별 token bucket, 복원·삭제 회계와 아직 남은 단일 인스턴스 한계를 실제 코드와 PR을 바탕으로 정리했습니다.
-
코어를 SaaS에서 떼어냈더니 경계가 하나 더 필요했다 — JDK-only 엔진과 thin host 설계
reputation-pool의 판단 엔진을 JDK-only 공개 코어로, 인증·멀티테넌시·운영 기능을 Spring Boot SaaS host로 분리한 과정을 다룹니다. 처음에는 gRPC 계약과 어댑터가 reference server 안에 있어 cloud가 코드를 복사해야 했습니다. 이 잘못된 경계를 공개 reputation-pool-grpc 모듈로 다시 나누고, server와 cloud가 같은 계약을 소비하게 만든 이유와 비용을 실제 PR과 코드 구조를 바탕으로 정리했습니다.
-
32스레드 테스트는 통과했지만 명세가 틀렸다 — Lincheck가 동시성 계약을 세 번 기각한 과정
reputation-pool의 32스레드 스트레스 테스트를 Lincheck 모델 체킹으로 확장하면서 겪은 기록입니다. Lincheck가 찾아낸 것은 단순한 구현 버그가 아니었습니다. 전역 fencing token 순서, acquire가 반환할 리소스의 정체성, block과 경합할 때의 성공 여부처럼 제가 계약이라고 믿었던 세 가지 가정이 실제 구현이 보장해야 할 계약보다 강했습니다. 실패 trace를 따라 공개 계약과 스케줄링 정책을 분리하고, 선형화로 표현할 수 없는 운영 속성은 별도의 실시간 순서 테스트로 옮긴 과정을 정리했습니다.