콘텐츠로 이동

01. Host lifecycle

레퍼런스 목차

이 category는 Spring Boot host 등록 진입점과 ZLinkFrameworkRuntime이 제공하는 진입점을 다룬다. 정확한 signature는 Java 공통 runtime exact interface와 Java 구성과 host exact interface가 소유한다.


@EnableZLinkFramework + ZLinkFrameworkConfigurer (구성 시점)

Framework root를 Spring application context에 한 번 등록한다. 다른 모든 항목의 전제 조건이다.

@Configuration
@EnableZLinkFramework
public class GameFrameworkConfig {

    @Bean
    ZLinkFrameworkConfigurer gameConfigurer() {
        return options -> {
            ZLinkMeshNodeBuilder play = options.addRouteMesh("play")
                .listen(5501)
                .setRoutingIdPrefix("play")
                .setPlacementWeight(100);
        };
    }
}

옵션. 이 호출에는 다음 modifier가 붙는다.

Modifier 기본값 의미
@EnableZLinkFramework 필수 Spring starter의 auto-configuration을 활성화한다
ZLinkFrameworkConfigurer bean (configure(ZLinkFrameworkOptions)) 필수 topology, handler, Location Store 등 모든 등록의 진입점이다. 여러 bean을 등록하면 모두 순서대로 적용된다

완료 결과. 반환값 없이 동기로 등록된다. Spring context 초기화(bean 생성) 시점에 구성을 검증하고, 실패하면 ZLinkConfigurationException으로 startup 자체를 실패시킨다 — 잘못된 구성이 message 처리 중에 처음 나타나지 않는다.

선택 기준. 모든 host가 정확히 한 번(하나 이상의 configurer bean으로) 등록한다. ZLinkFrameworkOptions의 topology·handler 등록 세부는 topology-discovery category를 참고한다. Application은 ZLinkFrameworkRuntime을 직접 생성·시작하지 않는다 — Spring starter가 SmartLifecycle.start()로 소유한다.


relocate

현재 host가 들고 있는 stateful object(User Spot·Actor)를 다른 eligible node로 이전한다. 계획된 점검이나 rolling update 전에 호출한다.

ZLinkFrameworkRelocationOptions options = new ZLinkFrameworkRelocationOptions(
    ZLinkFrameworkRelocationMode.ROLLING_UPDATE,
    2L,
    Duration.ofMinutes(5));

ZLinkFrameworkRelocationResult result = runtime.relocate(options)
    .toCompletableFuture().get();

if (result.outcome() == ZLinkFrameworkRelocationOutcome.RELOCATED) {
    runtime.shutdown().toCompletableFuture().get();
}

옵션. ZLinkFrameworkRelocationOptions의 component는 다음과 같다.

Component 기본값 의미
mode 필수 PLANNED_MAINTENANCE(source와 같은 application version만 target) 또는 ROLLING_UPDATE(지정한 version만 target)
targetApplicationVersion PLANNED_MAINTENANCE에서는 null(source 값 사용), ROLLING_UPDATE에서는 필수(source보다 커야 함) 목표 application version. 조합이 맞지 않으면 시작 전 IllegalArgumentException으로 거부한다
deadline null이면 Framework 기본 deadline eligible target 수렴을 기다리는 상한

완료 결과. ZLinkFrameworkRelocationResult.outcome()이 RELOCATED면 모든 object 이전이 끝나고 host는 RELOCATED 상태가 된다(새 operation은 받지 않지만 infrastructure는 유지한다). BLOCKED면 reason()에 TARGET_UNAVAILABLE·STORE_UNAVAILABLE·DEADLINE_EXCEEDED 등이 담긴다. 각 호출은 shared operation 결과를 따르는 전용 CompletableFuture view를 반환한다 — toCompletableFuture().cancel(...)은 그 waiter만 해제하며 host operation 자체는 계속 진행된다.

선택 기준. 배포 전 무중단 이전이 필요할 때 사용한다. 이전 없이 바로 종료하려면 shutdown을 직접 호출한다. 같은 mode·target version으로 중복 호출하면 진행 중인 operation에 합류하고, 다른 값으로 호출하면 BLOCKED/OPERATION_IN_PROGRESS로 완료한다.


shutdown

Host를 종료한다. Relocation을 시작하지 않는다 — 이전이 필요하면 먼저 relocate를 호출한다.

ZLinkFrameworkTerminationResult result = runtime.shutdown(Duration.ofSeconds(30))
    .toCompletableFuture().get();

옵션. 이 호출에는 다음 modifier가 붙는다.

Modifier 기본값 의미
shutdown() 없음(overload) Framework 기본 deadline 사용
shutdown(Duration deadline) — 종료 정리 상한. 초과하면 FORCE_STOPPED로 완료한다

완료 결과. ZLinkFrameworkTerminationResult.outcome()이 STOPPED(정상 정리) 또는 FORCE_STOPPED(deadline 초과·정리 실패)다. SERVING에서 호출하면 남은 application 처리와 resource를 정리하고, RELOCATED에서 호출하면 infrastructure 연결만 정리한다.

선택 기준. Host를 종료할 때 항상 호출한다. RELOCATING 도중 호출하면 진행 중인 atomic relocation unit의 결과만 확정하고 나머지는 시작하지 않는다 — 그 relocation을 기다리던 호출자는 BLOCKED/SHUTDOWN_REQUESTED를 받는다.


status / observe (읽기·관찰)

Host의 현재 상태를 한 번 읽거나, 상태 변화를 실시간으로 관찰한다.

ZLinkFrameworkRuntimeStatus status = runtime.status();
boolean canAcceptNewOperations = status.isReady() && status.acceptingWork();

runtime.observe().subscribe(new Flow.Subscriber<>() {
    // onNext(observed)에서 observed.status(), observed.loss()를 확인한다
});

옵션. 이 진입점에는 modifier가 없다 — status()는 인자가 없고, observe()는 Flow.Publisher<ZLinkObservedStatus<ZLinkFrameworkRuntimeStatus>>를 반환한다.

완료 결과. status()는 동기 호출이다. isReady()는 state() == SERVING일 때만 true이고, acceptingWork()는 새 application operation 수락 여부를 나타낸다 — 두 값이 다를 수 있으므로 둘 다 확인한다. observe()는 terminal 완료 없이 스트리밍하며, ZLinkObservedStatus.loss() (coalescedCount/discardedTerminalCount)로 관찰 유실 여부를 판단한다.

선택 기준. 지금 이 순간의 상태 한 번만 필요할 때 status()를, 상태 전이를 놓치지 않고 계속 받으려면 observe()를 사용한다. Spring Boot Actuator HealthIndicator를 구현할 때도 이 status()를 읽어 Health.up()/Health.outOfService()를 결정한다 — Framework가 별도 health builder를 제공하지 않으므로 이 판단은 application의 HealthIndicator bean이 직접 작성한다.


전체 근거는 Java 공통 runtime exact interface와 Java 구성과 host exact interface를 참고한다.