QAUP_Management/doc/work/20250110_环境变量配置方案.md

18 KiB
Raw Permalink Blame History

生产环境配置管理方案 - 纯环境变量方案

日期: 2025-01-10 版本: v1.0 适用场景: Docker部署环境下修改API接口配置无需重新打包jar


📋 需求背景

当前生产环境使用Docker部署方式每次修改 application-prod.yml 都需要重新打包jar包流程繁琐。

期望: 只修改配置文件,重启应用即可生效,无需重新打包。


🎯 解决方案:纯环境变量方案

方案特点

特性 说明
无需重新打包 只修改 .env 文件
修改简单 纯文本编辑
回滚容易 备份 .env 文件即可
版本控制 可保存多个环境的 .env
安全性 敏感信息不打包到jar
环境隔离 开发/测试/生产用不同 .env

工作原理

Spring Boot 支持使用环境变量覆盖配置文件中的值:

# application-prod.yml 中定义
data:
  collector:
    airport-api:
      base-url: ${AIRPORT_API_BASE_URL:http://localhost:8090}
      #         ↑环境变量名        ↑默认值(环境变量不存在时使用)

当启动应用时,如果环境变量 AIRPORT_API_BASE_URL 存在,则使用环境变量的值;否则使用默认值。


🔧 实施步骤

Step 1: 修改 application-prod.yml一次性修改

文件位置: qaup-admin/src/main/resources/application-prod.yml

修改内容:

# 数据采集配置
data:
  collector:
    # 数据采集间隔(可选配置)
    interval: ${DATA_COLLECTOR_INTERVAL:250}

    detection:
      # 检测间隔(可选配置)
      interval: ${DATA_DETECTION_INTERVAL:1000}

    # 机场数据源配置
    airport-api:
      # API基础URL环境变量覆盖
      base-url: ${AIRPORT_API_BASE_URL:http://localhost:8090}

      endpoints:
        login: /login
        refresh: /userInfoController/refreshToken
        aircraft: /openApi/getCurrentFlightPositions
        vehicle: /openApi/getCurrentVehiclePositions
        arrival-route: /runwayPathPlanningController/findArrTaxiwayByRunwayAndContactCrossAndSeat
        departure-route: /runwayPathPlanningController/findDepTaxiwayByRunwayAndContactCrossAndSeat
        aircraft-status: /aircraftStatusController/getAircraftStatus
        flight-notification: /openApi/getInboundAndOutboundFlightsNotification

      # 认证信息(环境变量覆盖)
      auth:
        username: ${AIRPORT_API_USERNAME:dianxin}
        password: ${AIRPORT_API_PASSWORD:dianxin@123}

    # 无人车厂商数据源配置
    vehicle-api:
      # API基础URL环境变量覆盖
      base-url: ${VEHICLE_API_BASE_URL:http://localhost:8091}

      endpoints:
        vehicle-command: /api/VehicleCommandInfo
        universal-status: /api/v1/vehicles/{vehicleId}/status

      # 超时和重试配置(可选)
      timeout: ${VEHICLE_API_TIMEOUT:1000}
      retry-attempts: ${VEHICLE_API_RETRY:3}

    # 无人车数据持久化配置
    unmanned-vehicle:
      persistence:
        enabled: true
        batch-size: 50
        location-retention-days: 90
        command-retention-days: 365
      command:
        timeout: 1000
        retry-attempts: 3
        validation:
          enabled: true
          strict-mode: false

  retention:
    redis-expire-seconds: 60
    postgresql-days: 30

修改完成后: 重新打包一次jar包这是最后一次打包

cd qaup-admin
mvn clean package -DskipTests

Step 2: 修改启动脚本 qaup.sh

文件位置: 项目根目录 qaup.sh

完整内容:

#!/bin/sh
# ./qaup.sh start 启动 stop 停止 restart 重启 status 状态
AppName=qaup-admin.jar

# JVM参数
JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"

APP_HOME=`pwd`
LOG_PATH=$APP_HOME/logs/$AppName.log
ENV_FILE=$APP_HOME/.env

if [ "$1" = "" ];
then
    echo -e "\033[0;31m 未输入操作名 \033[0m  \033[0;34m {start|stop|restart|status} \033[0m"
    exit 1
fi

if [ "$AppName" = "" ];
then
    echo -e "\033[0;31m 未输入应用名 \033[0m"
    exit 1
fi

function start()
{
    PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`

    if [ x"$PID" != x"" ]; then
        echo "$AppName is running..."
    else
        # ========== 新增:加载环境变量 ==========
        if [ -f "$ENV_FILE" ]; then
            echo "Loading environment variables from $ENV_FILE"
            # 导出环境变量,忽略注释和空行
            export $(cat $ENV_FILE | grep -v '^#' | grep -v '^$' | xargs)
            echo "Environment variables loaded successfully"
        else
            echo "Warning: $ENV_FILE not found, using default configuration"
        fi
        # ========================================

        nohup java $JVM_OPTS -jar $AppName > /dev/null 2>&1 &
        echo "Start $AppName success..."
    fi
}

function stop()
{
    echo "Stop $AppName"

    PID=""
    query(){
        PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`
    }

    query
    if [ x"$PID" != x"" ]; then
        kill -TERM $PID
        echo "$AppName (pid:$PID) exiting..."
        while [ x"$PID" != x"" ]
        do
            sleep 1
            query
        done
        echo "$AppName exited."
    else
        echo "$AppName already stopped."
    fi
}

function restart()
{
    stop
    sleep 2
    start
}

function status()
{
    PID=`ps -ef |grep java|grep $AppName|grep -v grep|wc -l`
    if [ $PID != 0 ];then
        echo "$AppName is running..."
    else
        echo "$AppName is not running..."
    fi
}

case $1 in
    start)
    start;;
    stop)
    stop;;
    restart)
    restart;;
    status)
    status;;
    *)
    echo -e "\033[0;31m 未输入操作名 \033[0m  \033[0;34m {start|stop|restart|status} \033[0m"
esac

主要改动:

  1. 新增 ENV_FILE 变量指向 .env 文件
  2. start() 函数中加载环境变量
  3. 添加了提示信息

Step 3: 创建环境变量配置文件 .env

文件位置: jar包所在目录qaup.sh 同级)

文件内容:

# ============================================================
# QAUP 生产环境配置
# 环境变量配置文件
# 修改此文件后,执行 ./qaup.sh restart 即可生效
# ============================================================

# ========== 机场数据API配置 ==========
# 机场数据接口基础URL
AIRPORT_API_BASE_URL=http://192.168.1.100:8090

# 机场API认证信息
AIRPORT_API_USERNAME=dianxin
AIRPORT_API_PASSWORD=dianxin@123

# ========== 无人车厂商API配置 ==========
# 无人车厂商接口基础URL
VEHICLE_API_BASE_URL=http://192.168.1.101:8091

# 无人车API超时和重试配置可选单位毫秒
VEHICLE_API_TIMEOUT=1000
VEHICLE_API_RETRY=3

# ========== 数据采集配置(可选)==========
# 数据采集间隔(单位:毫秒)
DATA_COLLECTOR_INTERVAL=250

# 检测和推送间隔(单位:毫秒)
DATA_DETECTION_INTERVAL=1000

# ============================================================
# 注意事项:
# 1. 等号两边不要有空格
# 2. 字符串值不需要引号
# 3. #开头的行为注释
# 4. 修改后执行 ./qaup.sh restart 使配置生效
# ============================================================

设置文件权限推荐<EFBFBD><EFBFBD>:

# 只有owner可读写防止密码泄露
chmod 600 .env

📁 部署目录结构

/app/                          # 应用部署目录
├── qaup-admin.jar            # 应用jar包
├── qaup.sh                   # 启动脚本(已修改)
├── .env                      # 环境变量配置文件(新增)
├── logs/                     # 日志目录
│   └── qaup-admin.jar.log
└── config/                   # 可选:外部配置目录
    └── .env.backup-*         # 配置备份文件

🚀 日常使用流程

1. 修改API配置

# 编辑环境变量文件
vim .env

# 修改内容示例:
AIRPORT_API_BASE_URL=http://新服务器IP:8090
AIRPORT_API_USERNAME=新用户名
AIRPORT_API_PASSWORD=新密码
VEHICLE_API_BASE_URL=http://新服务器IP:8091

# 保存并退出
:wq

2. 重启应用使配置生效

./qaup.sh restart

输出示例:

Stop qaup-admin.jar
qaup-admin.jar (pid:12345) exiting...
qaup-admin.jar exited.
Loading environment variables from /app/.env
Environment variables loaded successfully
Start qaup-admin.jar success...

3. 验证配置是否生效

方法1: 查看日志

tail -f logs/qaup-admin.jar.log

查找包含 base-url 或 API调用相关的日志确认使用的是新地址。

方法2: 查看环境变量(启动前测试)

# 加载环境变量
export $(cat .env | grep -v '^#' | grep -v '^$' | xargs)

# 查看变量值
echo $AIRPORT_API_BASE_URL
echo $VEHICLE_API_BASE_URL

方法3: 使用管理端点(如果开启)

curl http://localhost:8080/actuator/env | grep AIRPORT_API

🔄 配置管理最佳实践

1. 备份配置

每次修改前备份:

# 备份到config目录
mkdir -p config
cp .env config/.env.backup-$(date +%Y%m%d-%H%M%S)

# 查看备份列表
ls -lh config/.env.backup-*

示例:

config/.env.backup-20250110-093000
config/.env.backup-20250110-143000
config/.env.backup-20250110-170000

2. 回滚配置

# 查看可用备份
ls config/.env.backup-*

# 恢复指定备份
cp config/.env.backup-20250110-093000 .env

# 重启应用
./qaup.sh restart

3. 多环境配置管理

准备不同环境的配置文件:

/app/config/
├── .env.dev          # 开发环境配置
├── .env.test         # 测试环境配置
├── .env.prod         # 生产环境配置
└── .env.dr           # 容灾环境配置

切换环境:

# 切换到测试环境
cp config/.env.test .env
./qaup.sh restart

# 切换到生产环境
cp config/.env.prod .env
./qaup.sh restart

4. 配置差异对比

# 对比当前配置和备份配置
diff .env config/.env.backup-20250110-093000

# 对比不同环境配置
diff config/.env.prod config/.env.test

🔒 安全建议

1. 文件权限控制

# .env 文件只允许owner读写
chmod 600 .env

# qaup.sh 可执行
chmod 755 qaup.sh

# jar包只读
chmod 444 qaup-admin.jar

2. Git版本控制

如果使用Git管理部署脚本务必排除敏感文件:

# 创建 .gitignore
cat > .gitignore << EOF
# 敏感配置文件
.env
.env.*

# 日志文件
logs/
*.log

# jar包通过CI/CD部署
*.jar

# 临时文件
*.tmp
*.swp
EOF

可以提交的文件:

  • qaup.sh - 启动脚本
  • .env.example - 配置模板(不含真实密码)

示例配置模板 (.env.example):

# ========== 机场数据API配置 ==========
AIRPORT_API_BASE_URL=http://your-airport-api-server:8090
AIRPORT_API_USERNAME=your-username
AIRPORT_API_PASSWORD=your-password

# ========== 无人车厂商API配置 ==========
VEHICLE_API_BASE_URL=http://your-vehicle-api-server:8091
VEHICLE_API_TIMEOUT=1000
VEHICLE_API_RETRY=3

# ========== 数据采集配置 ==========
DATA_COLLECTOR_INTERVAL=250
DATA_DETECTION_INTERVAL=1000

3. 密码管理建议

  • 使用强密码
  • 定期更换密码
  • 不同环境使用不同密码
  • 使用密钥管理工具(如 Vault、AWS Secrets Manager

📋 完整环境变量列表

必需环境变量

环境变量名 描述 默认值 示例
AIRPORT_API_BASE_URL 机场数据API基础URL http://localhost:8090 http://192.168.1.100:8090
AIRPORT_API_USERNAME 机场API用户名 dianxin dianxin
AIRPORT_API_PASSWORD 机场API密码 dianxin@123 SecurePass123
VEHICLE_API_BASE_URL 无人车API基础URL http://localhost:8091 http://192.168.1.101:8091

可选环境变量

环境变量名 描述 默认值 示例
VEHICLE_API_TIMEOUT 无人车API超时时间毫秒 1000 2000
VEHICLE_API_RETRY 无人车API重试次数 3 5
DATA_COLLECTOR_INTERVAL 数据采集间隔(毫秒) 250 500
DATA_DETECTION_INTERVAL 检测间隔(毫秒) 1000 1500

扩展环境变量(如果需要)

如果未来需要更多配置通过环境变量控制,可以继续扩展:

# 数据库配置
DB_HOST=localhost
DB_PORT=5432
DB_NAME=qaup
DB_USERNAME=postgres
DB_PASSWORD=123456

# Redis配置
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=

# 日志级别
LOG_LEVEL_QAUP=info
LOG_LEVEL_SPRING=warn

🧪 测试验证

1. 本地测试

# 1. 创建测试配置
cat > .env.test << EOF
AIRPORT_API_BASE_URL=http://test-airport:8090
AIRPORT_API_USERNAME=test-user
AIRPORT_API_PASSWORD=test-pass
VEHICLE_API_BASE_URL=http://test-vehicle:8091
EOF

# 2. 使用测试配置
cp .env.test .env

# 3. 启动应用
./qaup.sh start

# 4. 查看日志验证
tail -f logs/qaup-admin.jar.log | grep -E "airport|vehicle"

2. 配置验证脚本

创建验证脚本 verify-config.sh:

#!/bin/bash
# 配置验证脚本

echo "========== 环境变量配置验证 =========="

if [ ! -f .env ]; then
    echo "❌ .env 文件不存在"
    exit 1
fi

echo "✅ .env 文件存在"

# 加载环境变量
export $(cat .env | grep -v '^#' | grep -v '^$' | xargs)

# 验证必需变量
REQUIRED_VARS=(
    "AIRPORT_API_BASE_URL"
    "AIRPORT_API_USERNAME"
    "AIRPORT_API_PASSWORD"
    "VEHICLE_API_BASE_URL"
)

for var in "${REQUIRED_VARS[@]}"; do
    if [ -z "${!var}" ]; then
        echo "❌ 缺少必需环境变量: $var"
        exit 1
    else
        echo "✅ $var = ${!var}"
    fi
done

echo "========== 验证通过 =========="

使用:

chmod +x verify-config.sh
./verify-config.sh

🔧 故障排查

问题1: 环境变量未生效

症状: 修改了 .env 但应用仍使用旧配置

排查:

# 1. 确认 .env 文件格式正确(无空格、无引号)
cat .env

# 2. 手动测试环境变量加载
export $(cat .env | grep -v '^#' | grep -v '^$' | xargs)
echo $AIRPORT_API_BASE_URL

# 3. 确认应用已重启
./qaup.sh status
ps -ef | grep qaup-admin.jar

# 4. 查看启动日志
tail -100 logs/qaup-admin.jar.log

解决: 确保执行了 ./qaup.sh restart


问题2: .env 文件格式错误

常见错误:

# ❌ 错误:等号两边有空格
AIRPORT_API_BASE_URL = http://localhost:8090

# ❌ 错误:值使用了引号
AIRPORT_API_BASE_URL="http://localhost:8090"

# ❌ 错误:多余的导出语句
export AIRPORT_API_BASE_URL=http://localhost:8090

# ✅ 正确
AIRPORT_API_BASE_URL=http://localhost:8090

问题3: 权限问题

症状: 无法读取 .env 文件

# 检查文件权限
ls -l .env

# 修复权限
chmod 600 .env
chown app-user:app-group .env

📊 方案对比

与其他方案的对比

<EFBFBD><EFBFBD> 环境变量方案 外部配置文件 配置中心
修改便捷性
无需重新打包
是否需要重启 需要 需要 不需要
实施复杂度 简单 简单 中等
适用场景 生产环境 生产环境 企业级/微服务
成本 需要额外服务

🎯 总结

优点

  1. 无需重新打包jar - 修改 .env 即可
  2. 修改简单直观 - 纯文本编辑
  3. 回滚容易 - 备份/恢复 .env 文件
  4. 版本控制友好 - 可管理多环境配置
  5. 安全性好 - 敏感信息不打包到jar
  6. 环境隔离 - 不同环境使用不同配置
  7. 零成本 - 无需额外组件

适用场景

  • Docker部署环境
  • 多环境部署(开发/测试/生产)
  • 配置项以API地址、认证信息为主
  • 配置变更频率不高(月度/季度级别)

不适用场景

  • 需要实时配置生效(无法重启)
  • 配置项非常多且复杂
  • 微服务架构(建议使用配置中心)

🔄 后续优化方向

短期优化

  1. 配置校验: 启动前校验配置格式和必需项
  2. 配置加密: 敏感信息使用加密存储
  3. 配置模板: 提供不同场景的配置模板

长期规划

如果项目规模扩大、配置项增多建议引入配置中心Nacos/Apollo

  • 配置实时生效
  • 版本管理和灰度发布
  • 统一管理多服务配置
  • 配置变更审计

📚 参考资料

Spring Boot 配置文档

配置优先级

Spring Boot 配置加载优先级(从高到低):

  1. 命令行参数
  2. 操作系统环境变量 本方案使用
  3. application-{profile}.properties/yml (外部)
  4. application-{profile}.properties/yml (jar内)
  5. application.properties/yml (外部)
  6. application.properties/yml (jar内)

📞 支持与维护

常见问题

如遇到问题,请检查:

  1. .env 文件格式是否正确
  2. 是否执行了 ./qaup.sh restart
  3. 启动日志是否有错误信息
  4. 文件权限是否正确

配置变更记录

建议维护配置变更日志:

# 创建变更记录文件
cat > config/CHANGELOG.md << EOF
# 配置变更记录

## 2025-01-10 14:00
- 修改机场API地址: http://old:8090 -> http://new:8090
- 操作人: 张三
- 原因: 服务器迁移

## 2025-01-09 10:00
- 初始化生产环境配置
- 操作人: 李四
EOF

文档结束

最后更新: 2025-01-10 文档版本: v1.0 维护者: QAUP Team