본문으로 건너뛰기

[Ray Serve] ClusterNodeInfoCache 정렬 버그 수정 및 중복 GCS RPC 제거로 캐시 갱신 최적화

PR 링크: ray-project/ray#60843 상태: Merged | 변경: +52 / -13

들어가며

Ray Serve의 ClusterNodeInfoCache.update() 메서드에는 세 가지 문제가 있었습니다. 첫째, sorted(alive_nodes)가 새 리스트를 반환하는데 이를 무시하여 정렬이 적용되지 않았습니다. 둘째, ray._private.state.available_resources_per_node()가 레거시 GlobalStateAccessor를 통해 별도의 GCS 연결을 열어 중복 protobuf 직렬화/역직렬화를 수행했습니다. 셋째, 노드 레이블과 resources_total 같은 정적 속성을 매 틱마다 재구축했습니다.

핵심 코드 분석

Before: 정렬 버그와 중복 RPC

def update(self):
    # 정렬 결과를 무시! sorted()는 새 리스트를 반환
    sorted(alive_nodes)
    self._cached_alive_nodes = alive_nodes

    # 매 틱마다 정적 데이터 재구축
    self._cached_node_labels = {
        node_id.hex(): dict(node.labels) for (node_id, node) in nodes.items()
    }
    self._cached_total_resources_per_node = {
        node_id.hex(): dict(node.resources_total) for (node_id, node) in nodes.items()
    }

    # 레거시 경로로 별도 GCS 연결
    self._cached_available_resources_per_node = (
        ray._private.state.available_resources_per_node()
    )

After: in-place 정렬, 변경 감지, 기존 GCS 클라이언트 재사용

def update(self):
    alive_nodes.sort()  # in-place 정렬로 버그 수정
    self._cached_alive_nodes = alive_nodes

    # frozenset으로 클러스터 멤버십 변경 감지
    current_alive_ids = frozenset(node_id for node_id, _, _ in alive_nodes)
    if current_alive_ids != self._alive_node_id_set:
        self._alive_node_id_set = current_alive_ids
        self._cached_node_labels = { ... }  # 변경 시에만 재구축
        self._cached_total_resources_per_node = { ... }

    # 기존 GCS 클라이언트 재사용
    self._cached_available_resources_per_node = (
        self._fetch_available_resources_per_node()
    )

왜 이게 좋은가

  1. 정렬 버그 수정: sorted()list.sort()의 차이를 놓치면 결정론적 노드 순서 보장이 깨진다. in-place sort()로 올바르게 수정했다.
  2. 중복 GCS 연결 제거: 기존 GcsClient를 재사용하여 별도 연결 생성과 protobuf 직렬화/역직렬화 오버헤드를 제거했다.
  3. 변경 감지로 불필요한 재구축 방지: frozenset 비교를 통해 노드 멤버십이 바뀌지 않으면 정적 속성 재구축을 건너뛴다.

참고 자료

댓글

관련 포스트

PR Analysis 의 다른글