13.9.2.3 관제망 간섭 없는 마이크로초 컷 정밀 감사(Audit) 및 핀포인트 쿼리 명령법

13.9.2.3 관제망 간섭 없는 마이크로초 컷 정밀 감사(Audit) 및 핀포인트 쿼리 명령법

분산 파이프라인의 핵심인 오퍼레이터 노드에 Queryable (RPC) 백도어를 장착하여 관제 마스터가 내장을 파먹을 수 있게 허용했다면 (13.9.2.1, 13.9.2.2장 참조), 시스템 아키텍트는 즉시 심각한 딜레마에 부딪힌다.
초보 관제자가 심심하다고 0.001초마다 “현재 로봇 상태 내놔!” 라고 무차별 질의(Query Bomb)를 폭격 쳐대면 어떻게 될까? Zenoh-Flow 안에서 자율주행 모터를 죽어라 돌려야 할 C++ 오퍼레이터 코어가 관제탑의 쿼리 콜백(Query Handler)을 응답해 주느라 사이클을 다 빼앗겨 자율주행 레이턴시 망이 초토화되어 버리는 참사(Interference)가 벌어진다.

본 절에서는 관제망의 요구(Audit)가 파이프라인 본선 통신망과 C++ 연산 스레드에 티끌만 한 간섭(Zero-Interference)조차 내지 않도록 보호하는 마이크로초 컷 스레드 분리 런북과, 무식한 전체 덤프를 피하는 핀포인트(Pinpoint) URL 라우팅 체계를 갈파한다.

1. 콜백 스레드의 격리 불량과 연산 마비

declare_queryable 을 장착해 두면, 관제망이 질의를 날렸을 때 러스트(Tokio) 스케줄러가 데몬 안의 스레드 하나를 잡아다 유저의 C++ 코드로 밀어 넣는다.
만약 그 쿼리 콜백 안에서 덩치 큰 std::unordered_map 수십만 개를 memcpy로 직렬화(Serialize)하느라 5ms 가 소모된다면, 엣지 기기의 소중한 1개 코어는 5ms 동안 자율주행 텐서 연산을 전혀 태우지 못하는 치명적 침해를 입는다.
관제탑의 질의는 권리이지, 로봇 생존보다 우선될 수 없다!

2. Lock-free 백그라운드 스레드 도주(Escape) 전술

아키텍트는 오퍼레이터 코드 내부에 Mutex/Lock 이 난무하는 구시대적 변수 공유를 처형해야 한다. 관제용 콜백과 메인 파이프라인 연산은 철저히 Lock-Free 비동기 링 버퍼(Ring Buffer)나 원자적(Atomic) 포인터 치환 기법을 경유해 만난다.

// [파이프라인 간섭 배제 Zero-Copy 상태 절취 런북]

// 1. 파이프라인 연산 스레드는 무심하게 상태를 업데이트하고, 
// 그 포인터를 원자적으로 갱신(atomic::store)만 하고 1마이크로초 만에 사라진다.
std::atomic<shared_ptr<StateMatrix>> latest_state_ptr;

void OperatorNode::on_data(Data capsule) {
    auto new_state = compute(capsule);
    latest_state_ptr.store(new_state); // O(1) Atomic 치환의 극의!
    send_out();
}

// 2. 관제탑의 질의가 쏟아져 관문 콜백이 깨어날 때!
this->zs.declare_queryable("robot/kalman/get", [this](zenoh::Query%20q) {
    // Lock 이 없다! 메인 스레드가 무슨 연산을 하건 방해하지 않고 
    // 방금 전에 Atomic 하게 걸어둔 최신 포인터의 스냅샷 껍데기만 살짝 떠온다!
    auto state_snapshot = latest_state_ptr.load();
    
    // 이후 무거운 직렬화(Serialization)는 메인 파이프라인과 상관없는 
    // 이 잉여 스레드 속에서 알아서 오래 지지고 볶고, 응답을 던진다.
    q.reply(..., state_snapshot->serialize()).res(); 
});

이 우아한 원자(Atomic) 스택 교환술 덕분에, 자율주행 코어는 누군가 자기를 훔쳐보는지 아닌지 인지조차 하지 못한 채 자신의 레이턴시를 유지한다.

3. Selector 기반 핀포인트 쿼리 명령법의 도입

간섭은 줄였지만, 여전히 거대 변수 뭉텅이를 통째로 직렬화해 네트워크로 쏘는 짓은 대역폭(Bandwidth) 낭비다. “현재 속도” 하나가 궁금한데 “수만 개의 과거 궤적 맵” 까지 통째로 받아야 할 이유가 없다.

관제탑은 단순한 URI 문자열이 아니라, 리소스 속살을 바늘로 정밀하게 쑤시는 URL Path 기반 핀포인트 셀렉터(Selector) 를 이용해 쿼리를 날려야 한다.

# [관제 마스터의 핀포인트 바늘 쑤시기 런북]
# 무턱대고 노드 전체(robot/kalman)를 달라고 하지 않는다!
# 파라미터 계층을 파고들어 오직 "배터리" 혹은 "오차율" 만 달라고 경로(Path)를 명세한다.
replies = session.get("robot/kalman?target=velocity_only")

이를 받는 C++ 엣지 오퍼레이터 코드는 더는 맹목적으로 전체 구조체를 으깨지 않는다.

// [디스패치(Dispatch) 라우팅을 통한 극소 부위 적출술]
this->zs.declare_queryable("robot/kalman", [this](zenoh::Query%20q) {
    // 1. 관제탑이 진짜 내 전체 내장을 다 원하는지, 손톱만 원하는지 파싱한다!
    std::string target = q.key_expr().get_param("target");
    
    if (target == "velocity_only") {
        // [초정밀 적출!] 거대 복사 작업(Serialization) 0%. 
        // 오직 float 변수 1개, 단 4바이트만을 발라내어 응답 패킷에 포장해 던져버린다!
        float vel = latest_state_ptr.load()->current_velocity;
        q.reply(..., std::to_string(vel)).res();
    } else {
        // ... 전체 직렬화
    }
});

관제 마스터와 엣지 하드웨어 간의 L7 API 레이어를 Restful Selector 와 매개변수(Parameter)의 폭력성으로 구속시키는 행위.
원하는 데이터만 밀리초의 지연 없이 핀포인트로 뽑아내어 직렬화 CPU 파워 낭비를 0으로 소멸시키는 것. 이것이야말로 1만 대 로봇 스웜망의 0.1% 대역폭조차 불필요한 감방(Audit) 오버헤드로 채우지 않으려는 극한의 분산 쿼리 라우팅 철학이다.