gunicorn uvicorn worker.py limit_concurrency 설정을 존중하는 방법

Aug 19 2020

FastAPI는 gunicorn을 사용하여 다음에 설명 된대로 uvicorn 작업자를 시작합니다. https://www.uvicorn.org/settings/

그러나 gunicorn은 사용자 정의 설정으로 uvicorn을 실행할 수 없습니다. https://github.com/encode/uvicorn/issues/343

문제는 다음과 같은 소스 파일의 config_kwargs를 재정의하도록 제안되었습니다. https://github.com/encode/uvicorn/blob/master/uvicorn/workers.py

우리는 그것을 시도했지만 uvicorn은 limit_concurrency소스의 여러 uvicorn 파일 의 설정 을 따르지 않습니다 .

https://github.com/encode/uvicorn/blob/master/uvicorn/workers.py

# fail

        config_kwargs = {
            "app": None,
            "log_config": None,
            "timeout_keep_alive": self.cfg.keepalive,
            "timeout_notify": self.timeout,
            "callback_notify": self.callback_notify,
            "limit_max_requests": self.max_requests, "limit_concurrency": 10000,
            "forwarded_allow_ips": self.cfg.forwarded_allow_ips,
        }

https://github.com/encode/uvicorn/blob/master/uvicorn/main.py

# fail

    kwargs = {
        "app": app,
        "host": host,
        "port": port,
        "uds": uds,
        "fd": fd,
        "loop": loop,
        "http": http,
        "ws": ws,
        "lifespan": lifespan,
        "env_file": env_file,
        "log_config": LOGGING_CONFIG if log_config is None else log_config,
        "log_level": log_level,
        "access_log": access_log,
        "interface": interface,
        "debug": debug,
        "reload": reload,
        "reload_dirs": reload_dirs if reload_dirs else None,
        "workers": workers,
        "proxy_headers": proxy_headers,
        "forwarded_allow_ips": forwarded_allow_ips,
        "root_path": root_path,
        "limit_concurrency": 10000,
        "backlog": backlog,
        "limit_max_requests": limit_max_requests,
        "timeout_keep_alive": timeout_keep_alive,
        "ssl_keyfile": ssl_keyfile,
        "ssl_certfile": ssl_certfile,
        "ssl_version": ssl_version,
        "ssl_cert_reqs": ssl_cert_reqs,
        "ssl_ca_certs": ssl_ca_certs,
        "ssl_ciphers": ssl_ciphers,
        "headers": list([header.split(":") for header in headers]),
        "use_colors": use_colors,
    }

uvicorn이이 설정을 준수하도록 어떻게 강제 할 수 있습니까? FastAPI에서 여전히 503 오류가 발생합니다.

------- UPDATE ----------- --worker-connections 1000많은 작업자에게 배포되는 100 개의 병렬 요청을 만들 때 gunicorn 설정으로 인해 여전히 503이 발생합니다.

그러나 저는 이것이 좀 더 복잡한 문제라고 생각합니다. API 엔드 포인트는 많은 양의 워크로드를 처리하며 일반적으로 완료하는 데 5 초가 걸립니다.

코어 2 개, 작업자 2 개로 스트레스 테스트 :

  • A. 100 개 이상의 동시 요청, 엔드 포인트 과부하-작업자 연결 1
  • B. 100 개 이상의 동시 요청, 엔드 포인트 과부하-작업자 연결 1000 개
  • C. 100 개 이상의 동시 요청, 엔드 포인트 저 부하-작업자 연결 1
  • D. 100 개 이상의 동시 요청, 엔드 포인트 저 부하-작업자 연결 1000 개

두 실험 A와 B는 모두 503 개의 응답을 산출 했으므로 작업자 연결 설정이 작동한다고 가정하면 시뮬레이션 연결이 너무 많으면 503 오류가 발생하지 않는 것 같습니다.

우리는 gunicorn / uvicorn이 작업을 대기열에 넣고 503 오류를 발생시키지 않을 것으로 예상하기 때문에이 동작에 대해 의아해합니다.

답변

2 JPG Aug 19 2020 at 11:57

로부터 gunicorn의 문서

worker-connections

동시 클라이언트의 최대 수입니다.

그리고 uvicorn doc에서

limit-concurrency

HTTP 503 응답을 발행하기 전에 허용 할 최대 동시 연결 또는 작업 수입니다.

이 정보에 따르면 두 설정 변수 모두 동일한 작업을 수행합니다. 그래서

uvicorn --limit-concurrency 100 application:demo_app

거의 같다

gunicorn --worker-connections 100 -k uvicorn.workers.UvicornWorker application:demo_app

참고 : 나는 이것에 대한 실제 테스트 를 한 적이 없습니다 . 내가 틀렸다면 저를 수정하십시오.


또한, 당신은 설정할 수 있습니다 limit-concurrency(또는 limit_concurrency서브 클래 싱에 의해) uvicorn.workers.UvicornWorker클래스를

from uvicorn.workers import UvicornWorker


class CustomUvicornWorker(UvicornWorker):
    CONFIG_KWARGS = {
        "loop": "uvloop",
        "http": "httptools",
        "limit_concurrency": 100
    }

이제 이것을 명령과 CustomUvicornWorker함께 사용하십시오 gunicorn.

gunicorn -k path.to.custom_worker.CustomUvicornWorker application:demo_app

참고 : 당신이 검사 할 수 있습니다 self.config.limit_concurrencyCustomUvicornWorker값이 올바르게 설정되었는지 확인하기 위해 클래스입니다.