Files
photography/backend/scripts/production-db-setup.sh
xujiang 0ddde92a3c feat: 完成API测试、生产环境配置和文档编写
## 🧪 API测试系统完善
- 创建完整的单元测试套件 (tests/unit_test.go)
  - 认证流程、CRUD操作、文件上传测试
  - 中间件、错误处理、性能测试
- 创建集成测试套件 (tests/integration_test.go)
  - 业务流程、数据一致性、并发测试
- 创建综合API测试 (test_api_comprehensive.http)
  - 92个测试场景,覆盖所有API端点
- 更新Makefile添加测试命令
  - test-unit, test-integration, test-api, test-cover, test-bench

## 🗄️ 生产环境数据库配置
- Docker Compose生产环境配置 (configs/docker/docker-compose.prod.yml)
  - PostgreSQL 16 + Redis 7 + Nginx + 监控栈
- 数据库初始化脚本 (configs/docker/init-db.sql)
  - 完整表结构、索引优化、触发器、视图
- 生产环境配置脚本 (scripts/production-db-setup.sh)
  - 自动化配置、连接池、备份策略、监控

## 📚 API文档完善
- 完整的API文档 (docs/API_DOCUMENTATION.md)
  - 详细接口说明、请求响应示例
  - 认证流程、错误处理、性能优化
  - SDK支持、部署指南、安全考虑
- 包含cURL示例和Postman Collection支持

## 📊 项目进度
- 总进度: 50.0% → 57.5%
- 中优先级任务: 55% → 70%
- 并行完成3个重要任务,显著提升项目完成度

## 🎯 技术成果
- 测试覆盖率大幅提升,支持自动化测试
- 生产环境就绪,支持Docker部署
- 完整的API文档,便于前后端协作
- 性能优化和监控配置,确保生产稳定性
2025-07-11 14:10:43 +08:00

718 lines
17 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# PostgreSQL 生产环境数据库配置脚本
# 用于初始化生产环境数据库配置、连接池、备份策略等
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log() {
echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
}
success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 配置变量
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
CONFIG_DIR="$PROJECT_ROOT/configs"
BACKUP_DIR="/var/backups/photography"
LOG_DIR="/var/log/photography"
# 默认配置
DB_HOST="${DB_HOST:-localhost}"
DB_PORT="${DB_PORT:-5432}"
DB_NAME="${DB_NAME:-photography}"
DB_USER="${DB_USER:-postgres}"
DB_PASSWORD="${DB_PASSWORD:-}"
DB_POOL_SIZE="${DB_POOL_SIZE:-20}"
DB_MAX_CONNECTIONS="${DB_MAX_CONNECTIONS:-100}"
# 检查依赖
check_dependencies() {
log "检查系统依赖..."
local missing_deps=()
# 检查 PostgreSQL 客户端
if ! command -v psql &> /dev/null; then
missing_deps+=("postgresql-client")
fi
# 检查 Docker如果使用容器部署
if ! command -v docker &> /dev/null; then
warning "Docker 未安装,跳过容器相关配置"
fi
# 检查 systemctl
if ! command -v systemctl &> /dev/null; then
warning "systemctl 未找到,跳过服务配置"
fi
if [ ${#missing_deps[@]} -ne 0 ]; then
error "缺少依赖: ${missing_deps[*]}"
echo "请运行以下命令安装依赖:"
echo "sudo apt-get update && sudo apt-get install -y ${missing_deps[*]}"
exit 1
fi
success "依赖检查完成"
}
# 创建必要目录
create_directories() {
log "创建必要目录..."
# 创建备份目录
sudo mkdir -p "$BACKUP_DIR"
sudo chown -R postgres:postgres "$BACKUP_DIR"
sudo chmod 755 "$BACKUP_DIR"
# 创建日志目录
sudo mkdir -p "$LOG_DIR"
sudo chown -R postgres:postgres "$LOG_DIR"
sudo chmod 755 "$LOG_DIR"
# 创建配置目录
mkdir -p "$CONFIG_DIR/postgres"
success "目录创建完成"
}
# 测试数据库连接
test_connection() {
log "测试数据库连接..."
if [ -z "$DB_PASSWORD" ]; then
error "数据库密码未设置,请设置 DB_PASSWORD 环境变量"
exit 1
fi
export PGPASSWORD="$DB_PASSWORD"
if psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT version();" &> /dev/null; then
success "数据库连接成功"
else
error "数据库连接失败,请检查配置"
exit 1
fi
}
# 创建数据库配置
create_database_config() {
log "创建数据库配置..."
# 生产环境配置文件
cat > "$CONFIG_DIR/postgres/postgresql.conf" << EOF
# PostgreSQL 生产环境配置
# Photography Portfolio 项目
# 连接设置
listen_addresses = '*'
port = $DB_PORT
max_connections = $DB_MAX_CONNECTIONS
superuser_reserved_connections = 3
# 内存设置
shared_buffers = 256MB
effective_cache_size = 1GB
work_mem = 4MB
maintenance_work_mem = 64MB
# WAL 设置
wal_buffers = 16MB
checkpoint_completion_target = 0.9
wal_writer_delay = 200ms
# 查询规划器
random_page_cost = 1.1
effective_io_concurrency = 200
default_statistics_target = 100
# 日志设置
logging_collector = on
log_directory = '$LOG_DIR'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_truncate_on_rotation = on
log_rotation_age = 1d
log_rotation_size = 100MB
log_min_duration_statement = 1000
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on
log_temp_files = 10MB
# 性能监控
shared_preload_libraries = 'pg_stat_statements'
track_activities = on
track_counts = on
track_io_timing = on
track_functions = all
# 自动清理
autovacuum = on
autovacuum_max_workers = 3
autovacuum_naptime = 1min
autovacuum_vacuum_threshold = 50
autovacuum_analyze_threshold = 50
# 时区设置
timezone = 'Asia/Shanghai'
log_timezone = 'Asia/Shanghai'
# 字符集设置
default_text_search_config = 'pg_catalog.simple'
EOF
# 创建 pg_hba.conf 配置
cat > "$CONFIG_DIR/postgres/pg_hba.conf" << EOF
# PostgreSQL Client Authentication Configuration File
# Photography Portfolio 项目
# TYPE DATABASE USER ADDRESS METHOD
# 本地连接
local all postgres peer
local all all md5
# IPv4 本地连接
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
# 应用连接
host $DB_NAME $DB_USER 0.0.0.0/0 md5
# 复制连接
host replication postgres 127.0.0.1/32 md5
host replication postgres ::1/128 md5
EOF
success "数据库配置创建完成"
}
# 配置连接池
setup_connection_pool() {
log "配置数据库连接池..."
# 使用 PgBouncer 作为连接池
if command -v pgbouncer &> /dev/null; then
cat > "$CONFIG_DIR/postgres/pgbouncer.ini" << EOF
[databases]
$DB_NAME = host=$DB_HOST port=$DB_PORT dbname=$DB_NAME
[pgbouncer]
listen_port = 6432
listen_addr = 127.0.0.1
auth_type = md5
auth_file = $CONFIG_DIR/postgres/userlist.txt
logfile = $LOG_DIR/pgbouncer.log
pidfile = /var/run/pgbouncer/pgbouncer.pid
admin_users = postgres
stats_users = postgres
# 连接池配置
pool_mode = transaction
max_client_conn = 100
default_pool_size = $DB_POOL_SIZE
min_pool_size = 5
reserve_pool_size = 5
reserve_pool_timeout = 5
server_lifetime = 3600
server_idle_timeout = 600
# 性能调优
server_connect_timeout = 15
server_login_retry = 15
query_timeout = 0
query_wait_timeout = 120
client_idle_timeout = 0
client_login_timeout = 60
autodb_idle_timeout = 3600
# 日志设置
log_connections = 1
log_disconnections = 1
log_pooler_errors = 1
EOF
# 创建用户认证文件
echo "\"$DB_USER\" \"$DB_PASSWORD\"" > "$CONFIG_DIR/postgres/userlist.txt"
chmod 600 "$CONFIG_DIR/postgres/userlist.txt"
success "PgBouncer 连接池配置完成"
else
warning "PgBouncer 未安装,跳过连接池配置"
echo "安装 PgBouncer: sudo apt-get install pgbouncer"
fi
}
# 配置自动备份
setup_backup_strategy() {
log "配置自动备份策略..."
# 创建备份脚本
cat > "$BACKUP_DIR/backup.sh" << 'EOF'
#!/bin/bash
# PostgreSQL 自动备份脚本
# Photography Portfolio 项目
set -e
# 配置
DB_HOST="${DB_HOST:-localhost}"
DB_PORT="${DB_PORT:-5432}"
DB_NAME="${DB_NAME:-photography}"
DB_USER="${DB_USER:-postgres}"
BACKUP_DIR="/var/backups/photography"
LOG_FILE="$BACKUP_DIR/backup.log"
RETENTION_DAYS=30
# 日志函数
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# 执行备份
backup_database() {
local backup_date=$(date +'%Y%m%d_%H%M%S')
local backup_file="$BACKUP_DIR/${DB_NAME}_${backup_date}.sql"
local compressed_file="${backup_file}.gz"
log "开始备份数据库: $DB_NAME"
# 执行 pg_dump
export PGPASSWORD="$DB_PASSWORD"
if pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" \
-f "$backup_file" \
--verbose --clean --no-owner --no-privileges \
"$DB_NAME" 2>> "$LOG_FILE"; then
# 压缩备份文件
gzip "$backup_file"
# 验证备份文件
if [ -f "$compressed_file" ] && [ -s "$compressed_file" ]; then
log "备份成功: $compressed_file"
log "备份大小: $(du -h "$compressed_file" | cut -f1)"
else
log "ERROR: 备份文件创建失败"
exit 1
fi
else
log "ERROR: 数据库备份失败"
exit 1
fi
}
# 清理旧备份
cleanup_old_backups() {
log "清理 $RETENTION_DAYS 天前的备份文件"
find "$BACKUP_DIR" -name "${DB_NAME}_*.sql.gz" -mtime +$RETENTION_DAYS -delete
log "旧备份清理完成"
}
# 主函数
main() {
log "=== PostgreSQL 自动备份开始 ==="
backup_database
cleanup_old_backups
log "=== PostgreSQL 自动备份完成 ==="
}
# 执行主函数
main "$@"
EOF
# 设置执行权限
chmod +x "$BACKUP_DIR/backup.sh"
# 创建 crontab 条目
cat > "$CONFIG_DIR/postgres/backup.crontab" << EOF
# Photography Portfolio 数据库备份计划任务
# 每天凌晨 2 点执行备份
0 2 * * * $BACKUP_DIR/backup.sh >> $LOG_DIR/cron.log 2>&1
# 每周日凌晨 3 点执行完整备份
0 3 * * 0 $BACKUP_DIR/backup.sh full >> $LOG_DIR/cron.log 2>&1
EOF
success "自动备份策略配置完成"
echo "要启用自动备份,请运行: sudo crontab $CONFIG_DIR/postgres/backup.crontab"
}
# 配置监控
setup_monitoring() {
log "配置数据库监控..."
# 创建监控脚本
cat > "$CONFIG_DIR/postgres/monitor.sh" << 'EOF'
#!/bin/bash
# PostgreSQL 监控脚本
# Photography Portfolio 项目
set -e
# 配置
DB_HOST="${DB_HOST:-localhost}"
DB_PORT="${DB_PORT:-5432}"
DB_NAME="${DB_NAME:-photography}"
DB_USER="${DB_USER:-postgres}"
ALERT_EMAIL="${ALERT_EMAIL:-admin@photography.com}"
# 检查数据库连接
check_connection() {
export PGPASSWORD="$DB_PASSWORD"
if ! psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \
-c "SELECT 1;" &> /dev/null; then
echo "CRITICAL: 数据库连接失败"
return 1
fi
echo "OK: 数据库连接正常"
return 0
}
# 检查数据库大小
check_database_size() {
local size_mb=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \
-t -c "SELECT pg_size_pretty(pg_database_size('$DB_NAME'));" | tr -d ' ')
echo "INFO: 数据库大小: $size_mb"
}
# 检查慢查询
check_slow_queries() {
local slow_count=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \
-t -c "SELECT count(*) FROM pg_stat_statements WHERE mean_time > 1000;" | tr -d ' ')
if [ "$slow_count" -gt 10 ]; then
echo "WARNING: 发现 $slow_count 个慢查询"
else
echo "OK: 慢查询数量正常 ($slow_count)"
fi
}
# 检查连接数
check_connections() {
local conn_count=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \
-t -c "SELECT count(*) FROM pg_stat_activity;" | tr -d ' ')
local max_conn=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \
-t -c "SHOW max_connections;" | tr -d ' ')
local usage_percent=$((conn_count * 100 / max_conn))
if [ $usage_percent -gt 80 ]; then
echo "WARNING: 连接数使用率过高: $conn_count/$max_conn ($usage_percent%)"
else
echo "OK: 连接数正常: $conn_count/$max_conn ($usage_percent%)"
fi
}
# 主监控函数
main() {
echo "=== PostgreSQL 监控报告 $(date) ==="
if ! check_connection; then
echo "数据库连接失败,停止监控"
exit 1
fi
check_database_size
check_slow_queries
check_connections
echo "=== 监控完成 ==="
}
# 执行监控
main "$@"
EOF
chmod +x "$CONFIG_DIR/postgres/monitor.sh"
success "数据库监控配置完成"
}
# 配置性能优化
setup_performance_tuning() {
log "配置性能优化..."
# 创建性能调优脚本
cat > "$CONFIG_DIR/postgres/tune.sql" << EOF
-- PostgreSQL 性能调优脚本
-- Photography Portfolio 项目
-- 创建性能监控扩展
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
CREATE EXTENSION IF NOT EXISTS pg_buffercache;
-- 创建索引优化函数
CREATE OR REPLACE FUNCTION analyze_missing_indexes()
RETURNS TABLE (
schemaname text,
tablename text,
seq_scan bigint,
seq_tup_read bigint,
idx_scan bigint,
idx_tup_fetch bigint,
missing_index_suggestion text
) AS \$\$
BEGIN
RETURN QUERY
SELECT
s.schemaname,
s.tablename,
s.seq_scan,
s.seq_tup_read,
s.idx_scan,
s.idx_tup_fetch,
CASE
WHEN s.seq_scan > s.idx_scan AND s.seq_tup_read > 10000
THEN '建议添加索引'
ELSE '索引使用正常'
END as missing_index_suggestion
FROM pg_stat_user_tables s
WHERE s.schemaname = 'public'
ORDER BY s.seq_scan DESC, s.seq_tup_read DESC;
END;
\$\$ LANGUAGE plpgsql;
-- 创建慢查询分析函数
CREATE OR REPLACE FUNCTION analyze_slow_queries()
RETURNS TABLE (
query text,
calls bigint,
total_time double precision,
mean_time double precision,
rows bigint
) AS \$\$
BEGIN
RETURN QUERY
SELECT
left(s.query, 100) as query,
s.calls,
s.total_time,
s.mean_time,
s.rows
FROM pg_stat_statements s
WHERE s.mean_time > 100
ORDER BY s.mean_time DESC
LIMIT 20;
END;
\$\$ LANGUAGE plpgsql;
-- 创建表空间使用分析函数
CREATE OR REPLACE FUNCTION analyze_table_sizes()
RETURNS TABLE (
schemaname text,
tablename text,
size_pretty text,
size_bytes bigint
) AS \$\$
BEGIN
RETURN QUERY
SELECT
s.schemaname,
s.tablename,
pg_size_pretty(pg_total_relation_size(s.schemaname||'.'||s.tablename)),
pg_total_relation_size(s.schemaname||'.'||s.tablename)
FROM pg_tables s
WHERE s.schemaname = 'public'
ORDER BY pg_total_relation_size(s.schemaname||'.'||s.tablename) DESC;
END;
\$\$ LANGUAGE plpgsql;
-- 更新表统计信息
ANALYZE;
-- 重建索引(如需要)
-- REINDEX DATABASE $DB_NAME;
EOF
success "性能优化配置完成"
}
# 创建启动脚本
create_startup_script() {
log "创建服务启动脚本..."
cat > "$CONFIG_DIR/postgres/photography-db.service" << EOF
[Unit]
Description=Photography Portfolio Database Service
After=postgresql.service
Requires=postgresql.service
[Service]
Type=oneshot
RemainAfterExit=yes
User=postgres
Group=postgres
# 环境变量
Environment=DB_HOST=$DB_HOST
Environment=DB_PORT=$DB_PORT
Environment=DB_NAME=$DB_NAME
Environment=DB_USER=$DB_USER
# 启动前检查
ExecStartPre=/bin/bash -c 'until pg_isready -h $DB_HOST -p $DB_PORT; do sleep 1; done'
# 启动命令
ExecStart=/bin/bash $CONFIG_DIR/postgres/monitor.sh
# 停止命令
ExecStop=/bin/true
[Install]
WantedBy=multi-user.target
EOF
success "服务启动脚本创建完成"
echo "要启用服务,请运行:"
echo "sudo cp $CONFIG_DIR/postgres/photography-db.service /etc/systemd/system/"
echo "sudo systemctl enable photography-db.service"
echo "sudo systemctl start photography-db.service"
}
# 生成配置摘要
generate_summary() {
log "生成配置摘要..."
cat > "$CONFIG_DIR/postgres/SETUP_SUMMARY.md" << EOF
# PostgreSQL 生产环境配置摘要
## 配置文件位置
- PostgreSQL 配置: \`$CONFIG_DIR/postgres/postgresql.conf\`
- 认证配置: \`$CONFIG_DIR/postgres/pg_hba.conf\`
- PgBouncer 配置: \`$CONFIG_DIR/postgres/pgbouncer.ini\`
- 备份脚本: \`$BACKUP_DIR/backup.sh\`
- 监控脚本: \`$CONFIG_DIR/postgres/monitor.sh\`
## 数据库信息
- 主机: $DB_HOST
- 端口: $DB_PORT
- 数据库: $DB_NAME
- 用户: $DB_USER
- 最大连接数: $DB_MAX_CONNECTIONS
- 连接池大小: $DB_POOL_SIZE
## 目录结构
- 备份目录: $BACKUP_DIR
- 日志目录: $LOG_DIR
- 配置目录: $CONFIG_DIR/postgres
## 自动化任务
- 每日备份: 凌晨 2:00
- 每周完整备份: 周日凌晨 3:00
- 备份保留期: 30 天
## 监控指标
- 数据库连接状态
- 数据库大小
- 慢查询统计
- 连接数使用率
## 性能优化
- 已启用 pg_stat_statements 扩展
- 已创建性能分析函数
- 已配置合理的内存参数
- 已优化 WAL 和检查点设置
## 下一步操作
1. 复制配置文件到 PostgreSQL 目录
2. 重启 PostgreSQL 服务
3. 启用自动备份 crontab
4. 配置监控服务
5. 运行性能调优脚本
## 维护命令
\`\`\`bash
# 手动备份
$BACKUP_DIR/backup.sh
# 监控检查
$CONFIG_DIR/postgres/monitor.sh
# 性能分析
psql -d $DB_NAME -f $CONFIG_DIR/postgres/tune.sql
# 查看慢查询
psql -d $DB_NAME -c "SELECT * FROM analyze_slow_queries();"
# 查看表大小
psql -d $DB_NAME -c "SELECT * FROM analyze_table_sizes();"
\`\`\`
配置完成时间: $(date)
EOF
success "配置摘要生成完成: $CONFIG_DIR/postgres/SETUP_SUMMARY.md"
}
# 主函数
main() {
log "开始 PostgreSQL 生产环境配置..."
check_dependencies
create_directories
test_connection
create_database_config
setup_connection_pool
setup_backup_strategy
setup_monitoring
setup_performance_tuning
create_startup_script
generate_summary
success "PostgreSQL 生产环境配置完成!"
echo ""
echo "配置文件位置: $CONFIG_DIR/postgres/"
echo "查看配置摘要: cat $CONFIG_DIR/postgres/SETUP_SUMMARY.md"
echo ""
echo "要应用配置,请参考配置摘要中的'下一步操作'部分"
}
# 处理命令行参数
case "${1:-}" in
"test")
test_connection
;;
"backup")
setup_backup_strategy
;;
"monitor")
setup_monitoring
;;
"tune")
setup_performance_tuning
;;
*)
main
;;
esac