Python asyncio, 공유 상태 관리의 함정을 파헤치다!

by DD
3개월 전
조회수 12

Python의 asyncio는 공유 상태 관리 시 asyncio.Eventasyncio.Condition의 문제점을 드러냄

Polling 방식은 CPU 낭비, Event 방식은 상태 관리에 한계, Condition 방식은 빠른 상태 변화에 취약함

저자는 각 소비자별 큐(Queue)를 활용하여 상태 변화를 버퍼링하는 ValueWatcher 클래스를 제안함

ValueWatcher는 스레드 안전성, 타입 안전성, 다양한 대기 조건 지원 등 실용적인 기능을 제공함

asyncio.Event와 Condition의 한계

게시물에서는 asyncio.Event가 단일 상태 변화에만 적합하며, 여러 상태를 관리하기 어렵다고 지적한다. asyncio.Condition은 임의의 조건을 지원하지만, 빠른 상태 변화 시 업데이트 손실(Lost Update)이 발생할 수 있다. 특히, 상태가 빠르게 전환되는 경우, 대기 중인 소비자가 잘못된 상태를 확인하고 영원히 대기하는 문제가 발생할 수 있다. 이러한 문제점은 Inngest SDK 개발 과정에서 발견되었다고 언급된다.

ValueWatcher: 큐 기반의 상태 관리

저자는 각 소비자별로 asyncio.Queue를 사용하여 상태 변화를 큐에 저장하는 ValueWatcher 클래스를 제안한다. 이 방식은 상태 변화를 놓치지 않고, 여러 상태에 대한 대기를 효율적으로 처리할 수 있게 한다. ValueWatcher는 스레드 안전성을 위해 threading.Lock을 사용하고, 타입 안전성을 위해 typing.Generic을 활용한다. 또한, 다양한 대기 조건과 타임아웃 기능을 제공하여 실용성을 높였다.

ValueWatcher의 구현 상세

ValueWatcher 클래스는 스레드 안전성(Thread Safety)을 위해 threading.Lock을 사용하고, 상태 변경 시 모든 큐에 알림을 보낸다. wait_for 메서드는 큐를 등록하고, 현재 값을 확인한 후, 조건이 충족될 때까지 큐에서 값을 꺼낸다. 또한, set_if 메서드를 통해 조건부로 값을 설정하는 기능을 제공하여, 상태 머신(State Machine)의 구현을 용이하게 한다. 구체적인 구현 코드는 본문에 포함되어 있다.

ValueWatcher의 실용적 기능

ValueWatcher는 on_changeon_value 콜백을 지원하여 동기적인 소비자도 사용할 수 있도록 한다. 또한, wait_for_not_none과 같은 유틸리티 메서드를 제공하여 타입 안전성을 강화한다. 저자는 ValueWatcher를 Inngest의 Python SDK에서 WebSocket 연결 상태 관리, 워커 라이프사이클 관리, graceful shutdown 등에 활용했다고 밝힌다. 이러한 기능들은 ValueWatcher를 실제 프로덕션 환경에서 유용하게 사용할 수 있게 해준다.

What Python's asyncio primitives get wrong about shared state - Inngest Blog