feat: using asgi + uvicorn + gunicorn

This commit is contained in:
2025-09-19 10:15:25 +08:00
parent e3fa701f9f
commit b36c8183f2
5 changed files with 336 additions and 14 deletions
+4 -10
View File
@@ -26,16 +26,10 @@ pnpm run build
# 后端
后端使用 Django 框架开发,使用方法如下
后端使用 Django 框架开发,搭配 asgi + uvicorn + gunicorn 食用,运行`src/backend/start.sh`即可自动构建部署
## 安装软件包
若 venv 环境创建失败,请手动输入
```
pip install -r requirements.txt
```
## 部署
```
python manage.py runserver
```shell
apt install python3-venv
```
+33
View File
@@ -0,0 +1,33 @@
import multiprocessing
# 服务器绑定
bind = "0.0.0.0:8000"
# Worker设置
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = "uvicorn.workers.UvicornWorker"
worker_connections = 1000
# 超时设置
timeout = 30
keepalive = 2
max_requests = 1000
max_requests_jitter = 100
# 日志设置
loglevel = "info"
accesslog = "access.log"
errorlog = "error.log"
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s'
# 进程设置
preload_app = True
daemon = False
# 安全设置
user = None
group = None
tmp_upload_dir = None
# 性能调优
worker_tmp_dir = "/dev/shm"
+10 -4
View File
@@ -25,7 +25,7 @@ SECRET_KEY = "django-insecure-=)6qk8+!)hmy7x@7=svo#-^0$pe+3ya@as6afe^o2wj*m-5#3(
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['localhost', '127.0.0.1', '0.0.0.0', '*']
# Application definition
@@ -70,8 +70,7 @@ TEMPLATES = [
},
]
WSGI_APPLICATION = "item_manager.wsgi.application"
ASGI_APPLICATION = "item_manager.asgi.application"
# Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
@@ -121,7 +120,7 @@ CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
]
CORS_ALLOW_ALL_ORIGINS = True # 开发阶段允许所有源
CORS_ALLOW_ALL_ORIGINS = True
# Internationalization
@@ -140,6 +139,13 @@ USE_TZ = True
# https://docs.djangoproject.com/en/5.2/howto/static-files/
STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
# 安全设置(生产环境)
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = False # 如果使用HTTPS,设置为True
USE_X_FORWARDED_HOST = True
USE_X_FORWARDED_PORT = True
# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
Binary file not shown.
+289
View File
@@ -0,0 +1,289 @@
#!/bin/bash
# 自动部署Django ASGI服务器脚本
set -e # 遇到错误立即退出
echo "=== Django ASGI服务器自动部署脚本 ==="
echo "检测并安装必需的软件包..."
# 颜色输出定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 打印彩色消息
print_message() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_step() {
echo -e "${BLUE}[STEP]${NC} $1"
}
# 检测操作系统
detect_os() {
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
if [ -f /etc/debian_version ]; then
OS="debian"
PKG_MANAGER="apt-get"
elif [ -f /etc/redhat-release ]; then
OS="redhat"
PKG_MANAGER="yum"
else
OS="linux"
PKG_MANAGER="unknown"
fi
elif [[ "$OSTYPE" == "darwin"* ]]; then # MacOS 应该?能用?
OS="macos"
PKG_MANAGER="brew"
else
OS="unknown"
PKG_MANAGER="unknown"
fi
print_message "检测到操作系统: $OS"
}
# 检查并安装Python
check_python() {
print_step "检查Python安装..."
if command -v python3 &> /dev/null; then
PYTHON_VERSION=$(python3 --version 2>&1 | awk '{print $2}')
print_message "Python3 已安装,版本: $PYTHON_VERSION"
PYTHON_CMD="python3"
elif command -v python &> /dev/null; then
PYTHON_VERSION=$(python --version 2>&1 | awk '{print $2}')
if [[ $PYTHON_VERSION == 3.* ]]; then
print_message "Python 已安装,版本: $PYTHON_VERSION"
PYTHON_CMD="python"
else
print_error "需要Python 3.x,当前版本: $PYTHON_VERSION"
install_python
fi
else
print_warning "未检测到Python,开始安装..."
install_python
fi
}
# 安装Python
install_python() {
case $OS in
"debian")
sudo apt-get update
sudo apt-get install -y python3 python3-pip python3-venv
PYTHON_CMD="python3"
;;
"redhat")
sudo yum install -y python3 python3-pip
PYTHON_CMD="python3"
;;
"macos")
if ! command -v brew &> /dev/null; then
print_error "请先安装Homebrew: https://brew.sh/"
exit 1
fi
brew install python3
PYTHON_CMD="python3"
;;
*)
print_error "不支持的操作系统,请手动安装Python 3.8+"
exit 1
;;
esac
print_message "Python安装完成"
}
# 检查并安装pip
check_pip() {
print_step "检查pip安装..."
if command -v pip3 &> /dev/null; then
print_message "pip3 已安装"
PIP_CMD="pip3"
elif command -v pip &> /dev/null; then
print_message "pip 已安装"
PIP_CMD="pip"
else
print_warning "pip未安装,开始安装..."
install_pip
fi
}
# 安装pip
install_pip() {
case $OS in
"debian")
sudo apt-get install -y python3-pip
PIP_CMD="pip3"
;;
"redhat")
sudo yum install -y python3-pip
PIP_CMD="pip3"
;;
"macos")
# pip通常随Python一起安装
PIP_CMD="pip3"
;;
*)
# 使用get-pip.py脚本
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$PYTHON_CMD get-pip.py
rm get-pip.py
PIP_CMD="pip"
;;
esac
print_message "pip安装完成"
}
# 创建和激活虚拟环境
setup_virtual_env() {
print_step "设置Python虚拟环境..."
if [ ! -d "venv" ]; then
print_message "创建虚拟环境..."
$PYTHON_CMD -m venv venv
print_message "虚拟环境创建完成"
else
print_message "虚拟环境已存在"
fi
# 激活虚拟环境
source venv/bin/activate
print_message "虚拟环境已激活"
# 升级pip
pip install --upgrade pip
}
# 安装Python依赖
install_dependencies() {
print_step "安装Python依赖包..."
if [ -f "requirements.txt" ]; then
print_message "从requirements.txt安装依赖..."
pip install -r requirements.txt
else
print_message "requirements.txt不存在,安装基础依赖..."
pip install Django>=5.2.0 djangorestframework django-cors-headers gunicorn>=23.0.0 uvicorn>=0.35.0
# 创建requirements.txt
pip freeze > requirements.txt
print_message "已生成requirements.txt文件"
fi
print_message "依赖包安装完成"
}
# 初始化数据库
setup_database() {
print_step "初始化数据库..."
# 运行数据库迁移
print_message "应用数据库迁移..."
python manage.py makemigrations
python manage.py migrate
# 创建超级用户(如果不存在)
print_message "检查超级用户..."
python manage.py shell -c "
from django.contrib.auth.models import User
if not User.objects.filter(is_superuser=True).exists():
User.objects.create_superuser('admin', 'admin@example.com', 'admin123')
print('超级用户已创建 - 用户名: admin, 密码: admin123')
else:
print('超级用户已存在')
"
}
# 收集静态文件
collect_static() {
print_step "收集静态文件..."
python manage.py collectstatic --noinput --clear
print_message "静态文件收集完成"
}
# 检查端口占用
check_port() {
PORT=${1:-8000}
if command -v lsof &> /dev/null && lsof -Pi :$PORT -sTCP:LISTEN -t >/dev/null 2>&1; then
print_warning "端口 $PORT 已被占用,尝试终止进程..."
PID=$(lsof -ti:$PORT)
if [ ! -z "$PID" ]; then
kill -9 $PID
sleep 2
print_message "端口 $PORT 已释放"
fi
fi
}
# 启动服务器
start_server() {
print_step "启动Gunicorn ASGI服务器..."
# 检查端口
check_port 8000
# 启动服务器
exec gunicorn item_manager.asgi:application \
--bind 0.0.0.0:8000 \
--worker-class uvicorn.workers.UvicornWorker \
--workers 4 \
--timeout 30 \
--access-logfile - \
--error-logfile - \
--log-level info \
--reload
}
# 主函数
main() {
print_message "开始自动部署Django ASGI服务器..."
# 检测系统环境
detect_os
# 检查和安装必要软件
check_python
check_pip
# 设置虚拟环境
setup_virtual_env
# 安装依赖
install_dependencies
# 初始化数据库
setup_database
# 收集静态文件
collect_static
# 启动服务器
print_message "所有准备工作完成,启动服务器..."
echo ""
print_message "服务器信息:"
print_message "- 访问地址: http://localhost:8000"
print_message "- API地址: http://localhost:8000/api/"
print_message "- 管理后台: http://localhost:8000/admin/"
print_message "- 默认管理员: admin / admin123"
echo ""
start_server
}
# 错误处理
trap 'print_error "脚本执行失败,请检查错误信息"; exit 1' ERR
# 执行主函数
main "$@"