SynaptoRoute v0.4.0: 대규모 동시성 및 무중단 인덱싱을 위한 아키텍처 재설계
요약
SynaptoRoute v0.4.0은 대규모 동시성과 무중단 인덱싱을 위해 아키텍처를 재설계했습니다. ThreadPoolExecutor를 통한 임베딩 엔진 격리, 인메모리 WAL 도입, SQLite 풀링 최적화를 통해 고부하 상황에서도 낮은 지연 시간과 높은 가용성을 보장합니다.
핵심 포인트
- ThreadPoolExecutor를 사용하여 ONNX 추론과 asyncio 이벤트 루프를 격리
- 인메모리 WAL 도입으로 인덱스 재구축 중에도 무중단 라우팅 지원
- SQLite 풀링 및 Redis 동기화 최적화로 동시성 문제 해결
- 50,000개 이상의 경로에서도 안정적인 저지연 성능 유지
이 글은 SynaptoRoute v0.3.0: 50,000개의 경로로 확장하면서 시맨틱 라우터(Semantic Router) 매칭하기의 후속 글입니다. 처음 오신 분들을 위한 설명: SynaptoRoute는 API 호출 없이 사용자 질의를 로컬에서 결정론적 소프트웨어 로직으로 분류하는 고성능 시맨틱 라우팅 엔진(semantic routing engine)입니다.
우리가 마주한 벽
v0.3.0에서 우리는 SynaptoRoute가 표준 벤치마크(Banking77, CLINC150)에서 업계 표준에 부합하는 정확도를 증명하는 동시에, 50,000개의 밀집 경로(dense routes)에 대해 50ms 미만의 P99 지연 시간(latency)을 유지할 수 있음을 보여주었습니다.
하지만 규모(scale)는 단순히 전체 용량만을 의미하지 않습니다. 그것은 동시적인 변이(concurrent mutation)에 관한 문제입니다.
특히 과도한 비동기 부하(asynchronous load) 상황에서, 즉 시스템이 들어오는 질의를 라우팅하는 동시에 수백 개의 새로운 경로를 추가하려고 할 때, 아키텍처에서 균열이 나타나기 시작했습니다. FaissIndex는 재구축을 위해 전역 잠금(global locks)을 필요로 했습니다. FastEmbed의 수학적 실행은 asyncio 이벤트 루프(event loop)를 고갈시켰습니다. SQLite 연결은 여러 스레드에 걸쳐 ProgrammingError 예외를 발생시켰습니다. 그리고 우리의 새로운 RedisSyncManager는 10개의 복제본(replicas)이 동시에 동일한 상태 변경을 동기화할 때 O(N^2) 브로드캐스트 폭풍(broadcast storm)을 일으켰습니다.
v0.4.0에서 우리는 내부 엔진을 완전히 해체하고, 극단적인 적대적 혼돈(adversarial chaos) 속에서도 생존할 수 있도록 아키텍처를 완전히 재설계했습니다.
아키텍처 측면의 새로운 변화
1. ThreadPoolExecutor 격리
이전 버전에서 FastEmbedEncoder는 라우터와 동일한 실행 경로에서 수학적으로 밀집된 ONNX 추론(inference)을 실행했습니다. 트래픽이 높을 때, 이러한 순차적 연산은 비동기 이벤트 루프를 고갈시켰습니다.
v0.4.0에서는 임베딩 엔진을 전용 ThreadPoolExecutor로 명시적으로 격리했습니다. 이제 ONNX 하드웨어 추론은 asyncio로부터 완전히 분리되어, 순차적 연산 고갈을 방지하고 비동기 트래픽 급증 시 꼬리 지연 시간(tail latencies)을 획기적으로 완만하게 만듭니다.
2. 인메모리 쓰기 앞선 로그 (In-Memory Write-Ahead Log (WAL))
FaissIndex가 사전 할당된 용량(capacity)을 모두 소모하면 재구축(rebuild)을 수행해야 합니다. v0.3.0에서는 이 과정에서 라우터를 잠그고(locking), 메모리 재할당이 완료될 때까지 모든 유입되는 변이(mutations) 및 라우팅 요청을 차단해야 했습니다.
우리는 커스텀 **인메모리 쓰기 앞선 로그 (In-Memory Write-Ahead Log (WAL))**를 배포했습니다. 이제 인덱스가 활발히 재구축되는 동안, 라우터는 변이(add_route, delete_route)를 WAL에 버퍼링합니다. 유입되는 쿼리는 오래된 인덱스(stale index)와 WAL을 순차적으로 스캔하며, 이를 통해 대규모 백그라운드 인덱스 가비지 컬렉션 (Garbage Collection) 중에도 다운타임 없는 O(1) 처리량(throughput)을 달성합니다.
3. 제한된 SQLite 풀링 (Bounded SQLite Pooling) 및 O(1) Redis 동기화
멀티스레딩 데드락 (Deadlock) 문제를 해결하기 위해, 엄격한 스레드 로컬 격리(check_same_thread=True)를 갖춘 SQLiteStorage용 제한된 커넥션 풀 (Bounded Connection Pool)을 배포하여 멀티스레드 경합 잠금 (Contention locks)을 무력화했습니다.
클러스터 브로드캐스트 스톰 (Broadcast storm) 문제를 해결하기 위해, 명시적인 target_id 페이로드 (payload)를 활용하도록 RedisSyncManager를 업그레이드했습니다. 모든 변이 브로드캐스트를 재귀적으로 처리하는 대신, 이제 복제본(replicas)은 루프백 이벤트 (loopback events)를 즉시 폐기하여 동기화 네트워크 오버헤드를 O(N^2)에서 엄격한 선형 스케일링 (Linear scaling)으로 절감했습니다.
카오스 시뮬레이션 (The Chaos Simulation)
이러한 아키텍처 변경 사항이 효과가 있음을 경험적으로 증명하기 위해, 우리는 표준 순차 유닛 테스트 (Unit tests) 실행을 중단하고 **적대적 카오스 시뮬레이션 (Adversarial Chaos Simulation)**을 구축했습니다.
우리는 100개의 동시 스레드로 인메모리 SQLite 및 FAISS 인스턴스에 부하를 가했습니다:
- 50개의 동시 쓰기 작업 (Concurrent Writers): 손상된 라우트를 빠르게 주입하고 롤백 (Rollback)을 강제함.
- 50개의 동시 읽기 작업 (Concurrent Readers): 인덱싱 경계 (Indexing boundaries)를 공격적으로 트리거함.
결과 (85초 지속):
- 1,000건의 성공적인 라우트 변이 (Route mutations).
- 2,500건의 성공적인 읽기.
- 스레드 충돌 (Thread Crashes) 0건
- SQLite 잠금 (SQLite Locks) 0건
- 메모리 누수 (Memory Leaks) 0건
- 발화 중복 (Utterance Duplications) 0건
스레드 풀 (ThreadPool) 격리와 WAL 컨텍스트 매니저 (Context managers)가 완벽하게 작동했습니다.
독립적 하드웨어 검증
로컬 퍼스트 (Local-first) AI에서 반복적으로 등장하는 질문 중 하나는 하드웨어 결정론 (Hardware determinism)입니다. 클라우드 GPU에서 시맨틱 라우터 (Semantic router)를 실행할 때와 소비자용 노트북에서 실행할 때, 수학적 경계값이 변할까요?
우리는 다섯 가지의 서로 다른 소비자용 CPU (Intel 4C/8T부터 AMD 16C/24T까지)를 통해 SynaptoRoute v0.4.0을 독립적으로 테스트했습니다.
Banking77 데이터셋 결과:
- Top-1 정확도 (Accuracy): 모든 머신에서 92.85% ± 0.00%.
CLINC150 데이터셋 결과:
- Top-1 정확도 (Accuracy): 모든 머신에서 75.04% ± 0.00%.
우리는 기반이 되는 ONNX 추론 (Inference) 및 L2 정규화된 코사인 임계값 (L2-normalized cosine thresholds)이 엄격하게 결정론적임을 공식적으로 입증했습니다. 여러분의 라우팅 로직은 거대한 Kubernetes 클러스터에서와 마찬가지로 엣지 디바이스 (Edge device)에서도 동일하게 작동할 것입니다. 원시 지연 시간 (Raw latency)은 하드웨어에 따라 확장되지만, 논리적 정확도는 그렇지 않습니다.
다음 단계는 무엇인가요? (v0.5.0)
우리는 대규모 동시성 (Massive concurrency)을 위한 기반 인프라를 안정화했습니다. 이제 스택의 상위 계층으로 이동합니다.
v0.5.0 로드맵은 동적 경계 생성 (Dynamic Boundary Generation) 및 **멀티모달 통합 (Multi-Modal Integration)**에 집중하고 있습니다:
- Python 독스트링 (Docstrings)으로부터 의도 (Intents)를 자동으로 시딩 (Seeding)하기 위한 LLM 지원 합성 발화 생성 (Synthetic utterance generation).
- 네이티브 LangGraph
ToolNode주입. - 시각적 데이터 (
PIL.Image)를 라우터로 직접 수용하기 위한 CLIP/ImageBind 통합.
에이전트 워크플로우 (Agentic workflows) 또는 오케스트레이션 계층 (Orchestration layers)을 구축하고 있다면, v0.4.0을 사용해 보세요.
pip install synaptoroute==0.4.0
Repository: github.com/sitanshukr08/SynaptoRoute
PyPI: pypi.org/project/synaptoroute
높은 부하가 발생하는 프로덕션 환경에서 이를 실행하신다면, 관련 피드백을 듣고 싶습니다. 아래에 댓글을 남기거나 GitHub에 이슈 (Issue)를 생성해 주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기