Become a sponsor

说明
当单台服务器无法满足性能需求时,需要通过多实例部署和负载均衡来提升系统吞吐量。本文介绍本项目的水平扩展方案。
# gunicorn.conf.py
import multiprocessing
# 推荐公式:CPU 核心数 * 2 + 1
workers = multiprocessing.cpu_count() * 2 + 1
# Worker 类型
worker_class = 'gevent' # 异步 Worker,适合 I/O 密集型
# 超时时间
timeout = 120
# 最大请求数(防止内存泄漏)
max_requests = 1000
max_requests_jitter = 50
# 绑定地址
bind = '127.0.0.1:8000'| 类型 | 说明 | 适用场景 |
|---|---|---|
sync | 同步 Worker(默认) | CPU 密集型 |
gevent | 异步 Worker | I/O 密集型(推荐) |
uvicorn | ASGI Worker | 异步框架 |
http {
upstream djangoadmin {
# 轮询策略(默认)
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
}
server {
listen 80;
server_name your-domain.com;
# 前端静态文件
root /opt/project/ui/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# 后端 API 负载均衡
location /api/ {
proxy_pass http://djangoadmin;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}| 策略 | 配置 | 说明 |
|---|---|---|
| 轮询 | 默认 | 依次分配请求 |
| 权重 | weight=3 | 按权重分配 |
| IP Hash | ip_hash | 同一 IP 固定到同一后端 |
| 最少连接 | least_conn | 分配到连接数最少的后端 |
upstream djangoadmin {
# 权重策略:服务器配置不同按权重分配
server 127.0.0.1:8001 weight=3;
server 127.0.0.1:8002 weight=2;
server 127.0.0.1:8003 weight=1;
# IP Hash:需要 Session 粘性时使用
# ip_hash;
# 最少连接
# least_conn;
# 健康检查
server 127.0.0.1:8001 max_fails=3 fail_timeout=30s;
}项目使用 JWT 认证,天然支持多实例部署:
用户请求 → Nginx → 任意后端实例 → 验证 JWT → 返回响应1. 无状态:Token 自包含用户信息,无需服务端 Session
2. 无需共享存储:不需要 Redis 共享 Session
3. 任意路由:请求可以发到任意后端实例
4. 水平扩展:增加实例即可提升性能Token 黑名单
退出登录时 Token 加入 Redis 黑名单。多实例部署时,所有实例必须连接同一个 Redis,否则 Token 黑名单不生效。
多实例部署时,上传的文件需要所有实例都能访问:
# 服务器挂载 NFS
mount -t nfs storage-server:/data/uploads /opt/project/public/uploads使用 OSS/S3/MinIO 等对象存储:
# 配置对象存储
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_STORAGE_BUCKET_NAME = 'djangoadmin'
AWS_S3_ENDPOINT_URL = 'http://minio:9000'使用 Ceph、GlusterFS 等分布式文件系统。
多实例部署时,Redis 是关键的共享存储:
# 配置 Redis Sentinel
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://sentinel1:26379;redis://sentinel2:26379;redis://sentinel3:26379',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.SentinelClient',
'SENTINEL_KWARGS': {'sentinel_kwargs': {'password': 'sentinel_password'}},
'PASSWORD': 'redis_password',
}
}
}# 配置 Redis Cluster
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': [
'redis://node1:6379',
'redis://node2:6379',
'redis://node3:6379',
],
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.ClusterClient',
}
}
}# application/settings.py
DATABASES = {
'default': { # 主库(写)
'ENGINE': 'django.db.backends.mysql',
'HOST': 'master-db',
'PORT': 3306,
'NAME': 'djangoadmin',
'USER': 'root',
'PASSWORD': 'password',
},
'replica': { # 从库(读)
'ENGINE': 'django.db.backends.mysql',
'HOST': 'replica-db',
'PORT': 3306,
'NAME': 'djangoadmin',
'USER': 'root',
'PASSWORD': 'password',
},
}
# 数据库路由
DATABASE_ROUTERS = ['config.db_router.MasterSlaveRouter']# config/db_router.py
class MasterSlaveRouter:
"""主从数据库路由"""
def db_for_read(self, model, **hints):
return 'replica'
def db_for_write(self, model, **hints):
return 'default'
def allow_relation(self, obj1, obj2, **hints):
return True
def allow_migrate(self, db, app_label, model_name=None, **hints):
return db == 'default'; /etc/supervisor/conf.d/djangoadmin.conf
[program:djangoadmin-1]
command=/opt/venv/bin/gunicorn application.wsgi:application -c gunicorn.conf.py -b 127.0.0.1:8001
directory=/opt/project
user=www-data
autostart=true
autorestart=true
stdout_logfile=/var/log/djangoadmin/worker-1.log
[program:djangoadmin-2]
command=/opt/venv/bin/gunicorn application.wsgi:application -c gunicorn.conf.py -b 127.0.0.1:8002
directory=/opt/project
user=www-data
autostart=true
autorestart=true
stdout_logfile=/var/log/djangoadmin/worker-2.log
[program:djangoadmin-3]
command=/opt/venv/bin/gunicorn application.wsgi:application -c gunicorn.conf.py -b 127.0.0.1:8003
directory=/opt/project
user=www-data
autostart=true
autorestart=true
stdout_logfile=/var/log/djangoadmin/worker-3.log
[group:djangoadmin]
programs=djangoadmin-1,djangoadmin-2,djangoadmin-3Nginx 负载均衡需要健康检查来自动剔除故障节点:
upstream djangoadmin {
server 127.0.0.1:8001 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8002 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8003 max_fails=3 fail_timeout=30s;
}# application/health/views.py
def health_check(request):
"""健康检查端点"""
try:
with connection.cursor() as cursor:
cursor.execute("SELECT 1")
return JsonResponse({"status": "healthy"})
except Exception as e:
return JsonResponse({"status": "unhealthy", "error": str(e)}, status=503)多实例与负载均衡方案涵盖 Gunicorn 多 Worker、Nginx 负载均衡、JWT 无状态认证、文件存储共享、Redis 高可用、数据库读写分离、Supervisor 多实例配置、健康检查等方面。核心原则:无状态应用 + 共享存储 + 负载均衡。