318 lines
9.3 KiB
Bash
Executable File
318 lines
9.3 KiB
Bash
Executable File
#!/bin/bash
|
||
# 优化版启动脚本 - 整合 FastAPI 应用和队列消费者
|
||
|
||
set -e
|
||
|
||
# 默认配置
|
||
DEFAULT_HOST="0.0.0.0"
|
||
DEFAULT_PORT="8001"
|
||
DEFAULT_API_WORKERS="4"
|
||
DEFAULT_QUEUE_WORKERS="2"
|
||
DEFAULT_PROFILE="balanced"
|
||
DEFAULT_LOG_LEVEL="info"
|
||
DEFAULT_MAX_RESTARTS="3"
|
||
DEFAULT_CHECK_INTERVAL="5"
|
||
|
||
# 解析命令行参数
|
||
HOST=${HOST:-$DEFAULT_HOST}
|
||
PORT=${PORT:-$DEFAULT_PORT}
|
||
API_WORKERS=${API_WORKERS:-$DEFAULT_API_WORKERS}
|
||
QUEUE_WORKERS=${QUEUE_WORKERS:-$DEFAULT_QUEUE_WORKERS}
|
||
PROFILE=${PROFILE:-$DEFAULT_PROFILE}
|
||
LOG_LEVEL=${LOG_LEVEL:-$DEFAULT_LOG_LEVEL}
|
||
MAX_RESTARTS=${MAX_RESTARTS:-$DEFAULT_MAX_RESTARTS}
|
||
CHECK_INTERVAL=${CHECK_INTERVAL:-$DEFAULT_CHECK_INTERVAL}
|
||
|
||
# 颜色输出
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
print_color() {
|
||
local color=$1
|
||
local message=$2
|
||
echo -e "${color}${message}${NC}"
|
||
}
|
||
|
||
print_header() {
|
||
echo "=========================================================="
|
||
print_color $BLUE "Qwen-Agent 优化统一启动脚本"
|
||
echo "=========================================================="
|
||
echo
|
||
}
|
||
|
||
print_config() {
|
||
print_color $GREEN "启动配置:"
|
||
echo "- API服务器: http://$HOST:$PORT"
|
||
echo "- API工作进程: $API_WORKERS"
|
||
echo "- 队列工作线程: $QUEUE_WORKERS"
|
||
echo "- 性能配置: $PROFILE"
|
||
echo "- 日志级别: $LOG_LEVEL"
|
||
echo "- 最大重启次数: $MAX_RESTARTS"
|
||
echo "- 健康检查间隔: ${CHECK_INTERVAL}秒"
|
||
echo
|
||
}
|
||
|
||
setup_environment() {
|
||
print_color $YELLOW "设置环境变量..."
|
||
|
||
# 根据配置文件设置环境变量
|
||
case $PROFILE in
|
||
"low_memory")
|
||
export TOKENIZERS_PARALLELISM=false
|
||
export TOOL_CACHE_MAX_SIZE=20
|
||
;;
|
||
"balanced")
|
||
export TOKENIZERS_PARALLELISM=true
|
||
export TOKENIZERS_FAST=1
|
||
export TOOL_CACHE_MAX_SIZE=50
|
||
;;
|
||
"high_performance")
|
||
export TOKENIZERS_PARALLELISM=true
|
||
export TOKENIZERS_FAST=1
|
||
export TOOL_CACHE_MAX_SIZE=100
|
||
;;
|
||
esac
|
||
|
||
# 通用优化
|
||
export PYTHONUNBUFFERED=1
|
||
export PYTHONDONTWRITEBYTECODE=1
|
||
|
||
print_color $GREEN "环境变量设置完成"
|
||
}
|
||
|
||
create_directories() {
|
||
print_color $YELLOW "创建项目目录..."
|
||
|
||
directories=(
|
||
"projects/queue_data"
|
||
"projects/data"
|
||
"projects/uploads"
|
||
"projects/robot"
|
||
)
|
||
|
||
for dir in "${directories[@]}"; do
|
||
mkdir -p "$dir"
|
||
done
|
||
|
||
print_color $GREEN "项目目录创建完成"
|
||
}
|
||
|
||
check_dependencies() {
|
||
print_color $YELLOW "检查依赖..."
|
||
|
||
# 检查 Python 命令
|
||
if ! command -v python3 &> /dev/null; then
|
||
print_color $RED "错误: 未找到 python3 命令"
|
||
exit 1
|
||
fi
|
||
|
||
# 检查必需的包
|
||
local missing_packages=()
|
||
|
||
if ! python3 -c "import uvicorn" 2>/dev/null; then
|
||
missing_packages+=("uvicorn")
|
||
fi
|
||
|
||
if ! python3 -c "import fastapi" 2>/dev/null; then
|
||
missing_packages+=("fastapi")
|
||
fi
|
||
|
||
if [ ${#missing_packages[@]} -ne 0 ]; then
|
||
print_color $RED "错误: 缺少必需的包: ${missing_packages[*]}"
|
||
print_color $YELLOW "请运行: pip install ${missing_packages[*]}"
|
||
exit 1
|
||
fi
|
||
|
||
# 检查可选包
|
||
local optional_missing=()
|
||
|
||
if ! python3 -c "import psutil" 2>/dev/null; then
|
||
optional_missing+=("psutil")
|
||
fi
|
||
|
||
if ! python3 -c "import uvloop" 2>/dev/null; then
|
||
optional_missing+=("uvloop")
|
||
fi
|
||
|
||
if [ ${#optional_missing[@]} -ne 0 ]; then
|
||
print_color $YELLOW "提示: 缺少可选优化包: ${optional_missing[*]}"
|
||
print_color $YELLOW "建议运行: pip install -r requirements_optimization.txt"
|
||
fi
|
||
|
||
print_color $GREEN "依赖检查完成"
|
||
}
|
||
|
||
start_services() {
|
||
print_color $YELLOW "启动服务..."
|
||
|
||
# 启动 API 服务器
|
||
print_color $BLUE "启动 FastAPI 服务器..."
|
||
python3 -m uvicorn fastapi_app:app \
|
||
--host $HOST \
|
||
--port $PORT \
|
||
--workers $API_WORKERS \
|
||
--log-level $LOG_LEVEL \
|
||
--access-log \
|
||
> api_server.log 2>&1 &
|
||
|
||
API_PID=$!
|
||
echo "API 服务器 PID: $API_PID"
|
||
|
||
# 启动队列消费者
|
||
print_color $BLUE "启动队列消费者..."
|
||
python3 task_queue/consumer.py \
|
||
--workers=$QUEUE_WORKERS \
|
||
--worker-type=threads \
|
||
> queue_consumer.log 2>&1 &
|
||
|
||
CONSUMER_PID=$!
|
||
echo "队列消费者 PID: $CONSUMER_PID"
|
||
|
||
echo
|
||
print_color $GREEN "所有服务启动成功!"
|
||
print_color $GREEN "API 服务器: http://$HOST:$PORT"
|
||
echo "按 Ctrl+C 停止所有服务"
|
||
echo
|
||
}
|
||
|
||
monitor_services() {
|
||
local restart_counts=(0 0) # API, Consumer
|
||
|
||
while true; do
|
||
# 检查 API 服务器
|
||
if ! kill -0 $API_PID 2>/dev/null; then
|
||
print_color $RED "API 服务器意外停止"
|
||
|
||
if [ ${restart_counts[0]} -lt $MAX_RESTARTS ]; then
|
||
print_color $YELLOW "重启 API 服务器 (${restart_counts[0]} + 1/$MAX_RESTARTS)..."
|
||
python3 -m uvicorn fastapi_app:app \
|
||
--host $HOST \
|
||
--port $PORT \
|
||
--workers $API_WORKERS \
|
||
--log-level $LOG_LEVEL \
|
||
--access-log \
|
||
>> api_server.log 2>&1 &
|
||
|
||
API_PID=$!
|
||
restart_counts[0]=$((restart_counts[0] + 1))
|
||
print_color $GREEN "API 服务器重启成功,PID: $API_PID"
|
||
else
|
||
print_color $RED "API 服务器重启次数已达上限,停止所有服务"
|
||
break
|
||
fi
|
||
fi
|
||
|
||
# 检查队列消费者
|
||
if ! kill -0 $CONSUMER_PID 2>/dev/null; then
|
||
print_color $RED "队列消费者意外停止"
|
||
|
||
if [ ${restart_counts[1]} -lt $MAX_RESTARTS ]; then
|
||
print_color $YELLOW "重启队列消费者 (${restart_counts[1]} + 1/$MAX_RESTARTS)..."
|
||
python3 task_queue/consumer.py \
|
||
--workers=$QUEUE_WORKERS \
|
||
--worker-type=threads \
|
||
>> queue_consumer.log 2>&1 &
|
||
|
||
CONSUMER_PID=$!
|
||
restart_counts[1]=$((restart_counts[1] + 1))
|
||
print_color $GREEN "队列消费者重启成功,PID: $CONSUMER_PID"
|
||
else
|
||
print_color $RED "队列消费者重启次数已达上限,停止所有服务"
|
||
break
|
||
fi
|
||
fi
|
||
|
||
# 等待检查间隔
|
||
sleep $CHECK_INTERVAL
|
||
done
|
||
}
|
||
|
||
cleanup() {
|
||
echo
|
||
print_color $YELLOW "正在停止所有服务..."
|
||
|
||
# 停止 API 服务器
|
||
if [ ! -z "$API_PID" ] && kill -0 $API_PID 2>/dev/null; then
|
||
print_color $BLUE "停止 API 服务器 (PID: $API_PID)..."
|
||
kill $API_PID 2>/dev/null || true
|
||
|
||
# 等待优雅关闭
|
||
local count=0
|
||
while kill -0 $API_PID 2>/dev/null && [ $count -lt 10 ]; do
|
||
sleep 1
|
||
count=$((count + 1))
|
||
done
|
||
|
||
# 如果还未关闭,强制终止
|
||
if kill -0 $API_PID 2>/dev/null; then
|
||
print_color $RED "强制终止 API 服务器..."
|
||
kill -9 $API_PID 2>/dev/null || true
|
||
fi
|
||
fi
|
||
|
||
# 停止队列消费者
|
||
if [ ! -z "$CONSUMER_PID" ] && kill -0 $CONSUMER_PID 2>/dev/null; then
|
||
print_color $BLUE "停止队列消费者 (PID: $CONSUMER_PID)..."
|
||
kill $CONSUMER_PID 2>/dev/null || true
|
||
|
||
# 等待优雅关闭
|
||
local count=0
|
||
while kill -0 $CONSUMER_PID 2>/dev/null && [ $count -lt 10 ]; do
|
||
sleep 1
|
||
count=$((count + 1))
|
||
done
|
||
|
||
# 如果还未关闭,强制终止
|
||
if kill -0 $CONSUMER_PID 2>/dev/null; then
|
||
print_color $RED "强制终止队列消费者..."
|
||
kill -9 $CONSUMER_PID 2>/dev/null || true
|
||
fi
|
||
fi
|
||
|
||
print_color $GREEN "所有服务已停止"
|
||
exit 0
|
||
}
|
||
|
||
# 主函数
|
||
main() {
|
||
print_header
|
||
|
||
# 解析参数
|
||
if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
|
||
echo "用法: $0 [选项]"
|
||
echo
|
||
echo "环境变量选项:"
|
||
echo " HOST API绑定主机地址 (默认: $DEFAULT_HOST)"
|
||
echo " PORT API绑定端口 (默认: $DEFAULT_PORT)"
|
||
echo " API_WORKERS API工作进程数 (默认: $DEFAULT_API_WORKERS)"
|
||
echo " QUEUE_WORKERS 队列工作线程数 (默认: $DEFAULT_QUEUE_WORKERS)"
|
||
echo " PROFILE 性能配置文件: low_memory, balanced, high_performance (默认: $DEFAULT_PROFILE)"
|
||
echo " LOG_LEVEL 日志级别: debug, info, warning, error (默认: $DEFAULT_LOG_LEVEL)"
|
||
echo " MAX_RESTARTS 最大重启次数 (默认: $DEFAULT_MAX_RESTARTS)"
|
||
echo " CHECK_INTERVAL 健康检查间隔秒数 (默认: $DEFAULT_CHECK_INTERVAL)"
|
||
echo
|
||
echo "示例:"
|
||
echo " PROFILE=high_performance API_WORKERS=8 $0"
|
||
echo " PORT=8080 QUEUE_WORKERS=4 $0"
|
||
exit 0
|
||
fi
|
||
|
||
print_config
|
||
check_dependencies
|
||
setup_environment
|
||
create_directories
|
||
start_services
|
||
|
||
# 设置信号处理
|
||
trap cleanup SIGINT SIGTERM
|
||
|
||
# 监控服务
|
||
monitor_services
|
||
}
|
||
|
||
# 运行主函数
|
||
main "$@"
|