Zettelkasten

gunicorn worker

·수정 2026.04.23·수정 2

1. Gunicorn 이란?

• WSGI 서버 중 하나 (Python 웹앱 배포에 자주 사용) • 비동기 프레임워크가 아닌 WSGI 앱(Django, Flask 등)과 함께 사용 • Pre-fork 모델 기반으로 작동

2. Gunicorn 구조

flowchart TD
    A[Client Request] --> B[Gunicorn Master Process]
    B --> C1[Worker Process 1]
    B --> C2[Worker Process 2]
    B --> C3[Worker Process 3]
    B --> Cn[Worker Process N]
    
    C1 --> D[flask/Django]
    C2 --> D
    C3 --> D
    Cn --> D

    D --> E[Response to Client]
  • worker: 클라이언트 요청을 실제로 처리하는 하위 프로세스
  • Gunicorn은 메인 프로세스가 요청을 받아 worker에게 분배

3. Worker 종류

Worker 종류 인터페이스 특징
sync WSGI 기본 동기 worker
gevent, eventlet WSGI 비동기 worker, greenlet 사용
tornado WSGI Tornado 프레임워크 전용
uvicorn.workers.UvicornWorker ASGI 비동기 프레임워크용 (FastAPI 등)
  • 현재 서버에서 사용 가능한 워커는
    • sync, gevent, eventlet
    • sync는 동기적으로 처리
    • gevent. greenlet은 동시성 처리 가능
  • 동기, 비동기
    • 동기: 앞 작업이 끝날때까지 다른 작업을 시작하지 않음
    • 비동기: 작업을 중간에 멈추고 다른 작업을 동시에 진행할 수 있음
  • 동시성, 병렬성
    • 동시성: CPU 1개가 다른 디바이스 or 네트워크를 기다리는 동안, 다른 작업을 진행할 수 있는지?
    • 병렬성: 물리적으로 실제로 2개의 작업이 진행되는지? CPU가 2개 이상이어야함
    • 병렬성은 실제로는 동시성은 아니지만 동시성처럼 보일 수 있음
      • 동시에 여러작업을 진행하는 것처럼 보여서 계속 헷갈림?
  • 동시성/병렬성, 동기/비동기
    • 동기적으로는 동시성이 안됨
    • 동시성을 만족하기 위해선 비동기 동작을 만족 할 수 있어야함
      • 대변을 중간에 끊고 택배를 받을 수 있어야함

gevent 워커 동작 방식

왜 경량 스레드는 OS 스레드 보다 가볍지?

  1. 유저 모드 → 커널 모드 전환 으로 인한 인터럽트
  2. 전체 레지스터, 커널 스택 저장 필요
  3. 캐시 손실
  4. 스케줄러 오버헤드

Gevent에서 greenlet을 쓰는 방식

동작 방식

  • gevent는 libev(이벤트 루프)를 통해 greenlet들을 감시하고, 준비된 greenlet들을 실행함
import gevent

def task():
    print("running")

g = gevent.spawn(task)  # 내부적으로 Greenlet 생성
monkey.patch_all()

def fetch():
    s = socket.socket()
    s.connect(('example.com', 80))
    s.send(b"GET / HTTP/1.0\r\n\r\n")
    print(s.recv(1024))  # 비동기처럼 보이지만...

gevent.spawn(fetch)
  • recv()이 내부적으로 I/O Watcher에 등록됨
  • 블로킹 발생 시 → 현재 greenlet의 컨텍스트 저장 → Hub로 전환 -> 다른 스레드 실행
  • 이벤트 감지 시 → 다시 해당 greenlet으로 switch()

monkey patch?

  • 파이썬 기본 라이브러리가 블로킹 방식으로 동작해서, 동시성을 보장하기위해 monkey 패칭
  • 예시
    • socket.socket → gevent.socket.socket
    • time.sleep → gevent.sleep
    • ssl → gevent.ssl

gevent와 eventlet 차이

  • Python의 Green Thread 기반 동시성 라이브러리
  • 내부적으로 greenlet 사용
  • gevent와 비슷하지만, 구현 방식과 일부 API는 다름
항목 gevent eventlet
이벤트 루프 libev 사용 (C 빠름) 순수 Python
성능 빠름 상대적으로 느림
I/O 감시 libev select/poll/epoll 등
코드 베이스 C + Python 거의 Python
안정성 더 널리 쓰임 (Flask, Requests 등과 호환성 높음) 간단하고 순수 파이썬 기반

참고

greenlet의 동작 방식 동시성 구현 5가지 종류(자원관리, 서버 아키텍쳐 관점)