11.11.2.2 Queryable 증발 현상 분석 및 노드 다이그노스틱(Diagnostics) 점검
Zenoh 아키텍처는 일방적으로 트래픽을 토해내는(Publish) 행위 외에도, 분산망의 어느 특정 노드에게 데이터를 내놓으라고 강압하는 RPC(Remote Procedure Call) 성격의 쿼리 어블(Queryable) 인터페이스를 자랑한다. 클라우드의 관제탑이 특정 센서에 session.get('factory/robot/42/status') 명령을 후려쳤을 때, 분명히 그 로봇 전원이 켜져 있고 연결도 되어있음에도 도대체 응답(Reply)이 돌아오지 않고 허공으로 증발해버리는 “블랙홀(Blackhole)” 사태가 빈발한다.
이 비극은 네트워크 단절이 아니라, 라우팅 토폴로지 내부의 이름표(Key Expression) 미보유나 분산망 아키텍처 붕괴에 속한다. 본 절에서는 Querying 트랜잭션이 증발하는 기묘한 궤적을 해부하고, Zenoh 자체의 네트워크 건강 상태(Diagnostics)를 조회하여 시스템의 환부를 드러내는 방법론을 지시한다.
1. 경로 부재(Missing Route)와 라우팅 트리 붕괴 모형
로봇(Edge) 단말의 코드가 멀쩡하게 z_declare_queryable() 함수로 쿼리 인터페이스를 활성화시켰다 할지라도, 이 정보가 상위의 라우터망(Zenohd Router)에게 완벽히 등재전파(Propagation)되지 않으면 클라우드의 Get() 호출은 메아리치지 않는다.
쿼리어블 증발 원인 중 90% 이상은 가시성(Visibility) 의 붕괴다.
로봇이 “내 로봇 아이디는 42번이고 온도 쿼리에 응답할 준비가 되었다“라고 외치는 선언(Declare) 컨트롤 패킷이 순간적인 와이파이(Wi-Fi) 데드존에 의해 상위 라우터까지 배달되지 못한 경우다. 라우터의 해시 테이블(DHT)은 당연히 factory/robot/42/* 라는 대상이 존재하지 않는다고 인식하며, 클라우드로부터 쿼리 공격이 들어오는 그 즉시 이 요청 캡슐을 조용히 파기(Silent Drop)하고 발송자에게 타임아웃(Timeout) 징벌을 내린다.
2. 시스템 토폴로지 다이그노스틱(Diagnostics) 강제 복기
이러한 미스매치를 직관으로 때려잡으려 하지 마라. Zenoh는 이러한 전장 상황을 파악하기 위해 시스템 그 자체가 라우팅 정보를 스스로 고발하도록 특수한 백도어, 즉 @ 심볼로 시작하는 다이그노스틱 전용 어드민 쿼리망(Admin Space Query) 을 태생적으로 열어두고 있다.
관리자는 클라우드 터미널이나 로봇의 터미널 어디에서든 zenoh-cli로 망 전체의 토폴로지를 탈취(Interrogate)할 권한을 갖는다.
# 1. 쿼리 증발 사태가 벌어질 때, 대상 라우터의 "본인 인지 상태"를 조롱하듯 취조하라.
zenoh_get -e tcp/192.168.1.10:7447 -k "@/**/queryables"
명령을 발포하면 거대한 라우팅 망에 결속된 “모든 디바이스들의 리스트“와 “그들이 수신하겠다고 등록해놓은(Declared) 쿼리어블 키-값“이 JSON 뷰어로 끔찍할 만큼 상세하게 쏟아져 내린다.
{
"key": "@/router/0D34.../session/E92A.../queryable/factory/robot/42/status",
"value": "registered: true, routing_protocol: tcp"
}
만일 이 JSON 결과 덤프를 눈을 씻고 찾아봐도 문제의 그 로봇 42번 문자열이 보이지 않는다면? 로봇 단말 소프트웨어의 Zenoh 세션 초기화가 버그로 꼬여 다운되었거나, 브릿지가 꺼져있음이 물리적으로 증명된 것이다.
3. 와일드카드(Wildcard) 남용에 의한 분산 쿼리 응답(Reply) 파편화
라우트 테이블에 등록된 사실을 확인했음에도 응답 데이터가 반환되지 않고 찢어지는(Fragmented) 현상은 개발자의 안일한 와일드카드 억세스에서 연유한다.
z.get("factory/robot/**") 와 같이 무자비한 와일드카드로 쿼리를 난사했을 때, 대상이 된 500대의 로봇 관절 모터가 동시에 자기 통계 결과를 밀어 올리기 시작한다.
Zenoh 백엔드 수신 코드는 이 500방의 응답(Reply Channel)을 제한된 타임아웃(예: 2초) 안에 비동기 다중 콜백 스트림으로 퍼내야 한다.
// [응답의 소실을 부르는 안티패턴 처리]
replies := session.Get("factory/robot/**", zenoh.ConsolidationNone)
for reply := range replies {
// 500건의 응답을 파싱하는데 이곳 서버 디코딩 함수가 너무 느림! (병목)
processReply(reply)
}
// 제한시간이 끝나 채널이 끊기면 남은 400대의 로봇 쿼리 응답은 공중분해
만약 백엔드의 Go 서버가 한 대의 로봇 응답마다 무거운 DB 호출을 수반하여 루프(Loop)를 블로킹 시키면, Zenoh 콜 체인은 시간 초과(Timeout)에 직면하여 후속 로봇들의 반환 패킷을 무참히 절단(Close Channel)해 버린다.
“쿼리를 던졌는데 응답이 안 와요“라는 오열은 Zenoh 프로토콜의 쿼리 실패가 아니다. 당신의 백엔드 수신망이 그 집단 응답의 파도를 소화해 낼 동시성(Concurrency) 인프라 철학을 결여하고 템포를 놓쳐버린 개발자의 명백한 직무유기(Omission)다.