vault backup: 2026-06-01 23:17:01

This commit is contained in:
Rainyy21
2026-06-01 23:17:01 -04:00
parent 96449f8968
commit 8822f53104
6 changed files with 115 additions and 3 deletions
-175
View File
@@ -1,175 +0,0 @@
---
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)
-94
View File
@@ -1,94 +0,0 @@
---
aliases:
up: "[[00_devop_note]]"
tags:
- devop
---
w
# What is uWSGI?
**uWSGI** is an application server that sits between a web server (like Nginx or Apache) and a Python web application (like Django, Flask, or FastAPI). It runs your Python code and handles incoming web requests.
The name comes from **WSGI** (Web Server Gateway Interface), which is the standard Python spec (PEP 3333) that defines how web servers talk to Python applications. The lowercase "u" is the Greek letter μ (micro), suggesting it's lightweight — though in practice it grew into a full-featured server.
## Why do we need it?
A plain web server like Nginx doesn't know how to execute Python code. It only serves static files (HTML, CSS, images) and forwards dynamic requests elsewhere. You need a process that:
1. Loads your Python application into memory
2. Receives requests from the web server
3. Calls your Python code with the request
4. Returns the response back to the web server
That middle process is uWSGI (or alternatives like Gunicorn).
## The typical stack
```
Browser → Nginx → uWSGI → Python app (Django/Flask)
```
- **Nginx**: handles SSL, static files, load balancing, gzip, caching
- **uWSGI**: runs Python workers, manages processes/threads
- **Python app**: your business logic
Nginx and uWSGI usually talk over a **Unix socket** (fast, local) or a TCP port. The protocol between them is called the **uwsgi protocol** (lowercase) — a binary protocol that's faster than plain HTTP.
## Key features
- **Process management**: spawns multiple worker processes to handle concurrent requests
- **Threading**: each worker can run multiple threads
- **Auto-reload**: restart workers when code changes (dev mode)
- **Emperor mode**: one master process supervising many vassal apps
- **Cheaper mode**: dynamically scale workers up/down based on load
- **Multi-language**: despite the name, also supports Ruby, Perl, Go, etc.
## Minimal config example
A typical `uwsgi.ini`:
```ini
[uwsgi]
module = myproject.wsgi:application
master = true
processes = 4
threads = 2
socket = /tmp/myproject.sock
chmod-socket = 660
vacuum = true
die-on-term = true
```
- `module`: entry point (the WSGI callable)
- `processes`: how many worker processes to fork
- `socket`: where Nginx connects to
- `vacuum`: clean up the socket on exit
- `die-on-term`: shut down cleanly on SIGTERM
## Running it
```bash
uwsgi --ini uwsgi.ini
```
Or in production, run it under **systemd** so it restarts on failure.
## uWSGI vs Gunicorn
Both are WSGI servers. The community has largely shifted toward **Gunicorn** because:
- Simpler config
- Fewer footguns
- Easier to deploy
uWSGI is more feature-rich and faster in some benchmarks, but its config surface is huge (hundreds of options) and the project has had governance/maintenance concerns. For new projects, Gunicorn behind Nginx is the common default.
## When you'll see uWSGI
- Legacy Django/Flask deployments
- Setups that need uWSGI-specific features (Emperor, cheaper, etc.)
- Docker images for older Python web apps
## Related
- [[Apache Tomcat]] — the Java equivalent role (servlet container running Java apps behind a web server)