vault backup: 2026-05-30 16:02:33

This commit is contained in:
Rainyy21
2026-05-30 16:02:33 -04:00
commit 96449f8968
43 changed files with 2837 additions and 0 deletions
+175
View File
@@ -0,0 +1,175 @@
---
aliases:
up: "[[00_devop_note]]"
tags:
- devop
---
# Uvicorn and Gunicorn
Both are Python application servers — they run your Python web app and hand requests back and forth with a web server like Nginx. But they solve **different problems**, and you'll often see them used **together**.
The key split: **Gunicorn is WSGI** (synchronous), **Uvicorn is ASGI** (asynchronous).
## Quick refresher: WSGI vs ASGI
| | WSGI | ASGI |
|---|---|---|
| Spec | PEP 3333 | "Asynchronous Server Gateway Interface" |
| Model | Sync, one request per worker at a time | Async, many concurrent requests per worker |
| Frameworks | Django (classic), Flask | FastAPI, Starlette, Django (async views), Sanic |
| Supports WebSockets? | No | Yes |
| Supports HTTP/2, SSE? | No | Yes |
If your app uses `async def` view functions or WebSockets, you need ASGI.
If it's a traditional Django/Flask app with `def` views, WSGI is fine.
---
## Gunicorn ("Green Unicorn")
A **WSGI** server. Mature, simple, battle-tested. The de facto default for Django/Flask in production.
### Why people pick it
- **Simple config** — most options are sensible by default
- **Pre-fork worker model** — master process forks N workers; each worker handles one request at a time
- **Stable** — has been the standard for years
- **Good signal handling** — graceful reloads, zero-downtime restarts
### Minimal usage
```bash
gunicorn myproject.wsgi:application --workers 4 --bind 0.0.0.0:8000
```
Or with a config file `gunicorn.conf.py`:
```python
bind = "unix:/tmp/myproject.sock"
workers = 4
worker_class = "sync" # default
timeout = 30
accesslog = "-"
errorlog = "-"
```
### Worker classes
Gunicorn lets you swap the worker type:
- `sync` — default, one request at a time per worker
- `gthread` — threaded workers (good for I/O-bound apps)
- `gevent` / `eventlet` — async via greenlets (legacy)
- `uvicorn.workers.UvicornWorker` — **this is the bridge to ASGI** (see below)
### How many workers?
Rule of thumb: `(2 × CPU cores) + 1`. So a 4-core box → 9 workers.
---
## Uvicorn
An **ASGI** server built on `uvloop` and `httptools` — both written in C, which makes it very fast. It's the standard server for FastAPI and modern async Python web apps.
### Why people pick it
- **Async-native** — handles thousands of concurrent connections per worker
- **WebSockets + HTTP/2 support**
- **Very fast** — uvloop is a drop-in faster replacement for asyncio's event loop
- **Lightweight** — small dependency surface
### Minimal usage
```bash
uvicorn myproject.main:app --host 0.0.0.0 --port 8000
```
For development with auto-reload:
```bash
uvicorn myproject.main:app --reload
```
### Where it falls short alone
Uvicorn by itself is **single-process**. To use multiple CPU cores in production, you need to either:
1. Run multiple Uvicorn instances behind a load balancer, OR
2. Run Uvicorn **inside Gunicorn** as worker processes (the common pattern)
---
## The common production combo: Gunicorn + Uvicorn
This is the standard FastAPI production setup:
```bash
gunicorn myproject.main:app \
--workers 4 \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000
```
What's happening:
- **Gunicorn** is the process manager — forks workers, handles signals, restarts dead workers, manages graceful shutdowns
- **Uvicorn** runs *inside* each Gunicorn worker — provides the ASGI event loop that runs your async code
You get the best of both: Gunicorn's robust process management + Uvicorn's async performance.
### Visual
```
┌─ Uvicorn worker (async loop) ─ FastAPI app
│
Nginx → Gunicorn ├─ Uvicorn worker (async loop) ─ FastAPI app
(master) │
├─ Uvicorn worker (async loop) ─ FastAPI app
│
└─ Uvicorn worker (async loop) ─ FastAPI app
```
---
## Decision guide
| Your situation | Use |
|---|---|
| Django (sync), Flask | **Gunicorn** alone |
| FastAPI, Starlette, async Django | **Gunicorn + UvicornWorker** |
| Local dev, single FastAPI process | **Uvicorn** alone (`--reload`) |
| WebSockets required | Must be ASGI → **Uvicorn** (alone or under Gunicorn) |
| Legacy app, uWSGI already configured | [[uWSGI]] — no urgent need to migrate |
---
## Comparison with [[uWSGI]]
| | Gunicorn | Uvicorn | uWSGI |
|---|---|---|---|
| Protocol | WSGI | ASGI | WSGI (+ many others) |
| Async support | No (sync workers) | Yes (native) | Limited |
| Config complexity | Low | Low | **Very high** |
| WebSockets | No | Yes | Partial |
| Speed (raw) | Good | **Fastest** for async | Fast but heavy |
| Maintained actively | Yes | Yes | Concerns |
| Best for | Django/Flask | FastAPI | Legacy / specialized features |
---
## Common gotchas
1. **Don't run Uvicorn `--reload` in production** — it's a dev-only feature, has overhead and isn't safe.
2. **Workers ≠ threads** — each Gunicorn worker is a separate Python process with its own memory. Database connections, in-memory caches, etc. are *not* shared between workers.
3. **Timeouts matter** — Gunicorn's default `timeout=30s` will kill workers running long async tasks. Tune it for your workload.
4. **Nginx is still recommended in front** — Uvicorn/Gunicorn don't do SSL termination, static files, or rate limiting as well as Nginx.
5. **Logging** — by default both log to stdout/stderr; route to your log aggregator via container stdout (`-` in config).
---
## Related
- [[uWSGI]] — older alternative, mostly WSGI
- [[Apache Tomcat]] — the Java equivalent (servlet container)