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文档,便于前后端协作
- 性能优化和监控配置,确保生产稳定性
This commit is contained in:
xujiang
2025-07-11 14:10:43 +08:00
parent 5b3fc9bf9c
commit 0ddde92a3c
10 changed files with 4199 additions and 31 deletions

View File

@ -0,0 +1,718 @@
#!/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