플러팅 AI/Flask Server

Google Cloud Run에서 딥러닝 기반 서버 최적화: Connect 이벤트 비동기화와 Lazy Import 적용 사례

Solo.dev 2024. 12. 11. 03:49

Google Cloud Run에서 딥러닝 모델을 사용한 서버를 운영할 때, 초기화 비용과 리소스 관리 문제로 인해 응답 속도와 스케일링 비용이 증가하는 상황을 경험했습니다. 특히 Cold Start 상황에서 헬스체크와 WebSocket 연결 요청이 충돌하여 컨테이너가 불필요하게 추가 생성되는 문제가 발생했습니다.

이 글에서는 이러한 문제를 해결하기 위해 적용한 두 가지 주요 최적화 방법, Connect 이벤트 비동기화와 **Lazy Import(지연 임포트)**에 대해 공유합니다.


문제 상황

1. Cold Start 시 컨테이너 추가 생성

Google Cloud Run의 특성상, Cold Start 상태에서는 컨테이너가 첫 요청을 처리하기 위해 초기화됩니다. 이때, 아래와 같은 문제가 발생했습니다:

  • 헬스체크와 WebSocket 연결 요청이 거의 동시에 발생.
  • WebSocket 연결 처리가 동기적으로 실행되어 초기화 중인 컨테이너가 WebSocket 요청을 기다리지 못하고 새로운 컨테이너를 생성.
  • 결과적으로 불필요한 컨테이너가 생성되며 비용과 리소스 낭비 초래.

2. 딥러닝 라이브러리 초기화로 응답 속도 지연

YOLO, PaddleOCR, ONNXRuntime과 같은 딥러닝 라이브러리는 초기화 비용이 큽니다.

  • 서버 시작 시점에서 딥러닝 라이브러리를 임포트하면, Cold Start 시 초기화 작업이 헬스체크와 WebSocket 요청 응답을 지연시킴.
  • 이로 인해 Cloud Run의 헬스체크 실패, WebSocket 연결 시간 초과 등이 발생할 가능성이 높아짐.

해결 방안

1. Connect 이벤트를 비동기로 처리

WebSocket 연결 요청을 비동기로 처리하도록 설계 변경:

  • 기존에는 @socketio.on('connect') 이벤트에서 동기적으로 처리.
  • 이를 비동기로 변경하여 WebSocket 연결이 초기화 완료를 기다리지 않고 독립적으로 처리될 수 있도록 개선.

적용 코드:

@socketio.on('connect', namespace='/')
def handle_connect():
    # 비동기로 처리하여 초기화와 분리
    eventlet.spawn(handle_client_connection, request.sid)

2. Lazy Import로 초기화 지연

딥러닝 관련 라이브러리를 초기화 시점으로 이동:

  • YOLO, PaddleOCR, ONNXRuntime과 같은 라이브러리 임포트를 해당 모델이 실제로 로드되는 함수 내부로 이동.
  • 필요할 때만 임포트하도록 설계해 Cold Start 시 초기화 비용을 줄임.

적용 코드:

def load_yolo_model(self):
    try:
        # 지연 임포트
        sys.path.append(os.path.join(os.getcwd(), 'yolov5-master'))
        from utils.general import non_max_suppression 
        from models.common import DetectMultiBackend
       
        logger.info("YOLO 모델 로드 중...")
        model_weights = Path('yolov5-master/best.pt').resolve()
        self.yolo_model = DetectMultiBackend(str(model_weights), device='cpu')
        self.yolo_model.eval()
        logger.info("YOLO 모델 로드 완료.")
    except Exception as e:
        logger.error(f"YOLO 모델 로드 중 오류 발생: {e}")

예상 효과

1. Connect 이벤트 비동기화

  • WebSocket 연결 요청이 비동기로 처리되므로 Cold Start 컨테이너에서 헬스체크와의 충돌 방지.
  • 추가 컨테이너 생성 감소 및 비용 절감.

2. Lazy Import

  • 초기화 시간이 긴 딥러닝 라이브러리를 필요할 때만 로드.
  • 헬스체크와 WebSocket 연결 요청 응답 속도 개선.

테스트 결과

원래는 20초 넘게 걸리던 헬스체크와 SID 받는게 훨씬 빨라졌다 !
골칫거리였는데 해결해서 다행이다

 


결론

이번 최적화를 통해 Google Cloud Run에서 딥러닝 기반 서버를 보다 효율적으로 운영할 수 있는 가능성을 확인했습니다. 특히, Cold Start와 초기화 비용 문제는 서버 성능과 비용에 큰 영향을 미치며, 이를 해결하기 위해 비동기 처리Lazy Import 같은 전략이 유효한 해결책임을 알게 되었습니다.

여러분의 환경에서도 비슷한 문제가 발생한다면, 위에서 소개한 방법을 적용해보시길 추천드립니다. 특히, Google Cloud Run의 동적 스케일링 환경에서는 초기화 비용 관리가 매우 중요합니다.


참고

이 글이 여러분의 서버 최적화에 도움이 되길 바랍니다! 🚀

 
4o