콘텐츠로 이동

아키텍처

이 페이지는 작업 중입니다. 내용이 불완전하거나 변경될 수 있습니다.

Wippy는 Go 기반의 계층화된 시스템입니다. 컴포넌트는 의존성 순서로 초기화되고, 이벤트 버스를 통해 통신하며, 작업 스틸링 스케줄러를 통해 Lua 프로세스를 실행합니다.

계층컴포넌트
애플리케이션Lua 프로세스, 함수, 워크플로우
런타임Lua 엔진 (gopher-lua), 50+ 모듈
서비스HTTP, Queue, Storage, Temporal
시스템Topology, Factory, Functions, Contracts
코어Scheduler, Registry, Dispatcher, EventBus, Relay
인프라AppContext, Logger, Transcoder

각 계층은 아래 계층에만 의존합니다. 코어 계층은 기본 프리미티브를 제공하고, 서비스는 그 위에 더 높은 수준의 추상화를 구축합니다.

애플리케이션 시작은 네 단계로 진행됩니다.

컴포넌트가 로드되기 전에 핵심 인프라 생성:

컴포넌트목적
AppContext컴포넌트 참조를 위한 봉인된 딕셔너리
EventBus컴포넌트 간 통신을 위한 pub/sub
Transcoder페이로드 직렬화 (JSON, YAML, Lua)
Logger이벤트 스트리밍이 있는 구조화된 로깅
Relay메시지 라우팅 (Node, Router, Mailbox)

Loader가 토폴로지 정렬을 통해 의존성을 해결하고 레벨별로 컴포넌트를 로드합니다. 같은 레벨의 컴포넌트는 병렬로 로드됩니다.

코어 컴포넌트(PIDGen, Dispatcher, Registry, Finder, Supervisor)가 먼저 초기화되고, 이어서 시스템 컴포넌트(Topology, Lifecycle, Factory, Functions, Contracts)가 초기화됩니다. 구체적인 레벨은 런타임에 의존성 그래프로부터 계산되므로, 컴포넌트가 추가되거나 제거될 때 순서가 적응됩니다.

각 컴포넌트는 Load 단계에서 컨텍스트에 자신을 연결하여 의존 컴포넌트가 서비스를 사용할 수 있게 합니다.

모든 컴포넌트 로드 후:

  1. Dispatcher 동결 - 락 프리 조회를 위해 명령 핸들러 레지스트리 잠금
  2. AppContext 봉인 - 더 이상 쓰기 불가, 락 프리 읽기 활성화
  3. 컴포넌트 시작 - Starter 인터페이스가 있는 각 컴포넌트에 Start() 호출

레지스트리 엔트리(YAML 파일에서)가 로드되고 검증됩니다:

  1. 프로젝트 파일에서 엔트리 파싱
  2. 파이프라인 단계가 엔트리 변환 (override, link, bytecode)
  3. auto_start: true로 표시된 서비스 실행 시작
  4. 슈퍼바이저가 등록된 서비스 모니터링

컴포넌트는 애플리케이션 라이프사이클에 참여하는 Go 서비스입니다.

단계메서드목적
LoadLoad(ctx) (ctx, error)초기화 및 컨텍스트에 연결
StartStart(ctx) error활성 작업 시작
StopStop(ctx) error그레이스풀 셧다운

컴포넌트는 의존성을 선언합니다. 로더가 방향성 비순환 그래프를 구축하고 토폴로지 순서로 실행합니다. 셧다운은 역순으로 발생합니다.

컴포넌트의존성목적
PIDGen없음프로세스 ID 생성
DispatcherPIDGen명령 핸들러 디스패치
RegistryDispatcher엔트리 스토리지 및 버전닝
FinderRegistry엔트리 조회 및 검색
SupervisorRegistry서비스 재시작 정책
TopologySupervisor프로세스 부모/자식 트리
LifecycleTopology서비스 라이프사이클 관리
FactoryLifecycle프로세스 생성
FunctionsFactory상태 비저장 함수 호출

컴포넌트 간 통신을 위한 비동기 pub/sub.

  • 단일 디스패처 고루틴이 모든 이벤트 처리
  • 큐 기반 액션 전달로 퍼블리셔 블로킹 방지
  • 패턴 매칭으로 정확한 토픽과 와일드카드(*) 지원
  • 컨텍스트 기반 라이프사이클이 구독을 취소와 연결
sequenceDiagram
participant P as 퍼블리셔
participant B as EventBus
participant S as 구독자
P->>B: Publish(topic, data)
B->>B: 패턴 매치
B->>S: 액션 큐잉
S->>S: 콜백 실행

토픽은 <system>:<kind> 형식입니다. 내장 시스템이 발행합니다:

SystemKind목적
registryentry.create, entry.update, entry.delete, entry.accept, entry.reject엔트리 변경
registryregistry.begin, registry.commit, registry.discard트랜잭션 경계
processfactory.register, factory.delete, factory.accept, factory.reject프로세스 종류에 대한 팩토리 등록
supervisorservice.register, service.remove, service.update, service.start, service.stop서비스 라이프사이클

엔트리 정의를 위한 버전화된 스토리지.

  • 버전화된 상태 - 각 변경이 새 버전 생성
  • 히스토리 - 감사 추적을 위한 SQLite 백업 히스토리
  • 관찰 - 특정 엔트리의 변경 감시
  • 이벤트 기반 - 변경 시 이벤트 퍼블리시
flowchart LR
YAML[YAML 파일] --> Parser
Parser --> Stages[파이프라인 단계]
Stages --> Registry
Registry --> Validation
Validation --> Active

파이프라인 단계가 엔트리를 변환:

단계목적
Override설정 오버라이드 적용
Disable패턴으로 엔트리 제거
Link요구사항과 의존성 해결
BytecodeLua를 바이트코드로 컴파일
EmbedFS파일시스템 엔트리 수집

노드 간 프로세스 메시지 라우팅.

flowchart LR
subgraph Router
Local[로컬 노드] --> Peer[피어 노드]
Peer --> Inter[노드간]
end
Local -.- L[같은 프로세스]
Peer -.- P[같은 클러스터]
Inter -.- I[원격]
  1. Local - 같은 노드 내 직접 전달
  2. Peer - 클러스터 내 피어 노드로 전달
  3. Internode - 네트워크를 통해 원격 노드로 라우팅

각 노드에는 워커 풀이 있는 메일박스:

  • FNV-1a 해싱으로 발신자를 워커에 할당
  • 발신자별 메시지 순서 유지
  • 워커가 동시에 메시지 처리
  • 큐가 가득 차면 백프레셔

컴포넌트 참조를 위한 봉인된 딕셔너리.

속성동작
봉인 전부팅 중 단일 스레드 쓰기
봉인 후락 프리 읽기, 쓰기 시 패닉
중복 키패닉
타입 안전성타입화된 getter 함수

컴포넌트는 Load 단계에서 서비스를 연결합니다. 부트 완료 후 AppContext가 최적의 읽기 성능을 위해 봉인됩니다.

그레이스풀 셧다운은 역순으로 진행:

  1. SIGINT/SIGTERM이 셧다운 트리거
  2. 슈퍼바이저가 관리되는 서비스 중지
  3. Stopper 인터페이스가 있는 컴포넌트가 Stop() 수신
  4. 인프라 정리

두 번째 시그널은 즉시 종료를 강제합니다.