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 ถูกบังคับให้เป็นไปตามการตั้งค่านี้ได้อย่างไร? เรายังคงได้รับข้อผิดพลาด 503 จาก FastAPI

------- UPDATE ----------- การตั้งค่า gunicorn --worker-connections 1000ยังคงทำให้เกิด 503 เมื่อทำการร้องขอแบบขนาน 100 รายการที่แจกจ่ายให้กับผู้ปฏิบัติงานจำนวนมาก

อย่างไรก็ตามฉันเชื่อว่ามันเป็นปัญหาที่ซับซ้อนกว่าเล็กน้อย: จุดสิ้นสุด API ของเรามีภาระงานหนักจำนวนมากโดยปกติจะใช้เวลา 5 วินาทีในการทำให้เสร็จ

การทดสอบความเครียดด้วย 2 คอร์ 2 คนงาน:

  • ก. คำขอพร้อมกันมากกว่า 100 รายการจุดสิ้นสุดภาระหนัก - การเชื่อมต่อผู้ปฏิบัติงาน 1
  • B. คำขอพร้อมกันมากกว่า 100 คำขอปลายทางที่มีภาระหนัก - การเชื่อมต่อผู้ปฏิบัติงาน 1,000
  • C. 100+ คำขอพร้อมกันปลายทางโหลดต่ำ - การเชื่อมต่อผู้ปฏิบัติงาน 1
  • D. คำขอพร้อมกันมากกว่า 100 รายการจุดสิ้นสุดโหลดต่ำ - การเชื่อมต่อผู้ปฏิบัติงาน 1,000

การทดลองทั้งสองครั้ง A und 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_concurrencyในCustomUvicornWorkerชั้นเรียนเพื่อให้แน่ใจว่าได้ตั้งค่าอย่างถูกต้อง