asgi-server
npx skills add https://github.com/ingpdw/pdw-python-dev-tool --skill asgi-server
Agent 安装分布
Skill 文档
Uvicorn ASGI Server
Overview
Uvicorn is a lightning-fast ASGI server implementation for Python. Built on top of uvloop and httptools, it provides a minimal, high-performance interface for running asynchronous web frameworks such as FastAPI, Starlette, and other ASGI-compatible applications. Uvicorn supports HTTP/1.1, HTTP/2 (via the [standard] extras), WebSockets, and lifespan protocol events out of the box.
Key characteristics:
- High-throughput async I/O powered by
uvloop(when installed) - First-class support for FastAPI and Starlette applications
- Built-in hot reload for development workflows
- Multiprocess worker mode for production deployments
- SSL/TLS termination support
- WebSocket and HTTP/2 protocol support
- ASGI lifespan event handling for startup/shutdown logic
Install with standard extras for production-grade performance:
uv add "uvicorn[standard]"
The [standard] extras bundle includes uvloop, httptools, watchfiles (for reload), and websockets.
Development Mode
Run a FastAPI application in development with automatic code reloading:
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
Integrate with uv for virtual environment management:
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
Restrict reload watching to specific directories to avoid unnecessary restarts:
uvicorn app.main:app --reload --reload-dir src --reload-dir templates
The --reload flag uses watchfiles (if installed via [standard]) for efficient filesystem monitoring. Avoid using --reload in production — it is intended only for development.
CLI Options Reference
| Option | Default | Description |
|---|---|---|
--host |
127.0.0.1 |
Bind address. Use 0.0.0.0 to accept external connections. |
--port |
8000 |
Port number to listen on. |
--reload |
off | Enable auto-reload on code changes. |
--reload-dir |
. |
Directory to watch for changes (repeatable). |
--workers |
1 |
Number of worker processes (multiprocess mode). |
--log-level |
info |
Log verbosity: critical, error, warning, info, debug, trace. |
--access-log |
on | Enable access log. Use --no-access-log to disable. |
--proxy-headers |
off | Trust X-Forwarded-For and X-Forwarded-Proto headers. |
--forwarded-allow-ips |
127.0.0.1 |
Comma-separated IPs trusted for proxy headers. Use * for all. |
--ssl-keyfile |
none | Path to SSL private key file. |
--ssl-certfile |
none | Path to SSL certificate file. |
Programmatic Usage
Run Uvicorn programmatically within a Python script. This pattern is useful for debugging, testing, and IDE-based launch configurations.
import uvicorn
from app.main import app
if __name__ == "__main__":
uvicorn.run(
"app.main:app",
host="0.0.0.0",
port=8000,
reload=True,
log_level="info",
)
Pass the application as an import string ("app.main:app") when using reload=True so that uvicorn can re-import the module on changes. Pass the application object directly only when reload is disabled.
Programmatic Configuration Object
For more control, use uvicorn.Config and uvicorn.Server:
import uvicorn
config = uvicorn.Config(
"app.main:app",
host="0.0.0.0",
port=8000,
log_level="info",
access_log=True,
workers=1,
)
server = uvicorn.Server(config)
server.run()
This approach is useful when embedding uvicorn inside a larger application or when fine-grained control over server lifecycle is required.
Factory Pattern
Use the --factory flag when the application is created by a factory function rather than being a module-level object:
uvicorn app.main:create_app --factory
The factory function must be a zero-argument callable that returns an ASGI application:
# app/main.py
from fastapi import FastAPI
def create_app() -> FastAPI:
app = FastAPI(title="My API")
# Register routes, middleware, event handlers
from app.api import router
app.include_router(router)
return app
The factory pattern is preferred for larger applications because it avoids import side effects and enables cleaner testing and configuration.
Worker Configuration
For production deployments on multi-core machines, use the --workers flag to spawn multiple processes:
uvicorn app.main:app --workers 4 --host 0.0.0.0 --port 8000
Each worker runs its own event loop and handles requests independently. The --workers flag cannot be combined with --reload.
Calculate the optimal worker count based on available CPU cores:
workers = (2 * CPU_CORES) + 1
For I/O-bound applications (typical for FastAPI), this formula provides a good starting point. Tune based on actual load testing results.
For more robust multiprocess deployments, consider using Gunicorn with Uvicorn workers. Consult the deployment reference for Gunicorn integration patterns.
Logging Configuration
Basic Log Levels
Set the log level via CLI or programmatic configuration:
uvicorn app.main:app --log-level debug
Available levels in increasing verbosity: critical, error, warning, info, debug, trace.
Access Log Control
Disable access logs in production when a reverse proxy already handles request logging:
uvicorn app.main:app --no-access-log
Custom Log Configuration
Provide a custom logging configuration dictionary for structured or JSON logging:
import uvicorn
log_config = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"default": {
"fmt": "%(asctime)s %(levelname)s %(name)s %(message)s",
"datefmt": "%Y-%m-%d %H:%M:%S",
},
"access": {
"fmt": '%(asctime)s %(levelname)s %(client_addr)s - "%(request_line)s" %(status_code)s',
"datefmt": "%Y-%m-%d %H:%M:%S",
},
},
"handlers": {
"default": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stderr",
},
"access": {
"formatter": "access",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout",
},
},
"loggers": {
"uvicorn": {"handlers": ["default"], "level": "INFO", "propagate": False},
"uvicorn.error": {"level": "INFO"},
"uvicorn.access": {"handlers": ["access"], "level": "INFO", "propagate": False},
},
}
uvicorn.run("app.main:app", host="0.0.0.0", port=8000, log_config=log_config)
Pass a YAML or JSON file path to --log-config on the CLI for externalized log configuration.
Lifespan Handling
Uvicorn supports the ASGI lifespan protocol, which allows applications to run initialization and teardown logic on server start and stop.
Lifespan Modes
| Mode | Behavior |
|---|---|
on |
Always send lifespan events. Fail if the app does not handle them. |
off |
Never send lifespan events. |
auto |
Send lifespan events if the app supports them; ignore otherwise. Default. |
Set via CLI:
uvicorn app.main:app --lifespan auto
FastAPI Lifespan Context Manager
Define startup and shutdown logic with the FastAPI lifespan context manager:
from contextlib import asynccontextmanager
from collections.abc import AsyncIterator
from fastapi import FastAPI
@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
# Startup: initialize resources
app.state.db_pool = await create_db_pool()
app.state.redis = await create_redis_client()
yield
# Shutdown: release resources
await app.state.db_pool.close()
await app.state.redis.close()
app = FastAPI(lifespan=lifespan)
Use lifespan for database connection pools, cache clients, ML model loading, and other resources that require explicit initialization and cleanup.
HTTP/2 and WebSocket Support
HTTP/2
Enable HTTP/2 support by installing the [standard] extras and providing SSL certificates:
uvicorn app.main:app --ssl-keyfile key.pem --ssl-certfile cert.pem --http h2
HTTP/2 requires TLS. For local development, generate self-signed certificates with mkcert or openssl.
WebSockets
WebSocket support is included by default when websockets or wsproto is installed (bundled in [standard]). Select the implementation explicitly:
uvicorn app.main:app --ws websockets
# or
uvicorn app.main:app --ws wsproto
No additional configuration is required — FastAPI WebSocket endpoints work automatically.
Protocol Selection
Select the HTTP implementation explicitly when needed:
# Use httptools (default with [standard], fastest)
uvicorn app.main:app --http httptools
# Use h11 (pure Python, no C dependencies)
uvicorn app.main:app --http h11
# Use h2 for HTTP/2
uvicorn app.main:app --http h2 --ssl-keyfile key.pem --ssl-certfile cert.pem
The httptools implementation is recommended for production due to its superior throughput. The h11 implementation is useful when C extensions are unavailable or when debugging protocol-level issues.
SSL/TLS Configuration
Terminate TLS directly at Uvicorn when not running behind a TLS-terminating reverse proxy:
uvicorn app.main:app \
--ssl-keyfile /etc/ssl/private/server.key \
--ssl-certfile /etc/ssl/certs/server.crt \
--ssl-ca-certs /etc/ssl/certs/ca-bundle.crt \
--host 0.0.0.0 \
--port 443
For most production deployments, terminate TLS at the reverse proxy (Nginx, Caddy, or a cloud load balancer) and run Uvicorn on plain HTTP behind it. Consult the deployment reference for Nginx TLS termination patterns.
Running Behind a Reverse Proxy
When Uvicorn runs behind Nginx, Caddy, or a cloud load balancer, enable proxy header forwarding to preserve client IP addresses and protocol information:
uvicorn app.main:app \
--proxy-headers \
--forwarded-allow-ips "127.0.0.1,10.0.0.0/8" \
--host 0.0.0.0 \
--port 8000
--proxy-headerstells Uvicorn to trustX-Forwarded-ForandX-Forwarded-Protoheaders.--forwarded-allow-ipsrestricts which upstream IPs are trusted. Set to*only in fully trusted network environments.
Without these flags, request.client.host will always report the proxy’s IP rather than the actual client IP.
Resource Limits
Control connection and request limits to prevent resource exhaustion in production:
uvicorn app.main:app \
--limit-concurrency 100 \
--limit-max-requests 10000 \
--timeout-keep-alive 5 \
--host 0.0.0.0 --port 8000
| Option | Default | Description |
|---|---|---|
--limit-concurrency |
none | Maximum number of concurrent connections before rejecting new ones. |
--limit-max-requests |
none | Maximum requests per worker before restarting (guards against memory leaks). |
--timeout-keep-alive |
5 |
Seconds to wait for a new request on a keep-alive connection. |
--timeout-notify |
30 |
Seconds to wait for graceful shutdown of a worker. |
--backlog |
2048 |
Maximum length of the pending connections queue. |
Set --limit-max-requests in production to guard against gradual memory leaks. Combine with --workers so that restarting one worker does not drop all traffic.
Common Patterns
Integration with uv
Run Uvicorn through uv to ensure the correct virtual environment and dependencies:
# Development
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# Production
uv run uvicorn app.main:app --workers 4 --host 0.0.0.0 --port 8000
Environment-Based Configuration
Use environment variables or pydantic-settings to drive server configuration:
import uvicorn
from app.config import settings
if __name__ == "__main__":
uvicorn.run(
"app.main:app",
host=settings.server_host,
port=settings.server_port,
reload=settings.debug,
workers=settings.server_workers,
log_level=settings.log_level,
)
Health Check Endpoint
Pair Uvicorn with a health check endpoint for load balancer and orchestrator integration:
@app.get("/health")
async def health_check():
return {"status": "healthy"}
Binding to a Unix Socket
Bind Uvicorn to a Unix domain socket instead of a TCP port for communication with a local reverse proxy. This eliminates TCP overhead:
uvicorn app.main:app --uds /tmp/uvicorn.sock
Ensure the reverse proxy (Nginx or Caddy) is configured to proxy to the same socket path. Unix sockets are not accessible over the network and are only suitable when the proxy runs on the same host.
Restricting Reload File Types
During development, limit the file extensions that trigger a reload to avoid restarting on irrelevant file changes:
uvicorn app.main:app --reload --reload-include "*.py" --reload-include "*.yaml" --reload-exclude "test_*"
The --reload-include and --reload-exclude options accept glob patterns and can be repeated. This is particularly useful in projects with large static asset directories or generated files that should not trigger server restarts.
Cross-References
- For Docker deployment, consult the
docker-buildskill. - For FastAPI app configuration, consult the
fastapiskill. - For production deployment patterns with Gunicorn and Nginx, consult the deployment reference.
- For dependency management with uv, consult the
uvskill.