17 KiB
Raw Blame History

资金服务平台 Assembly 配置参考

项目专用配置详解

部署目录管理实践

核心原则:所有部署打包文件统一存储在项目根目录的 deploy/ 目录下,实现开发代码与部署产物的物理分离。

fundplatform/
├── deploy/                     # 部署产物目录(核心实践)
│   ├── fund-gateway.tar.gz     # 网关服务部署包
│   ├── fund-sys.tar.gz         # 系统服务部署包
│   ├── fund-cust.tar.gz        # 客户服务部署包
│   └── ... 其他服务部署包
├── scripts/                    # 统一脚本和配置
└── 各服务源代码目录            # 开发代码(与部署分离)

实践优势

  • 物理分离:开发代码与部署产物完全隔离
  • 版本管理便于CI/CD流水线统一管理部署包
  • 权限控制:可以对部署目录设置不同的访问权限
  • 清理维护:易于批量清理旧版本部署包

统一配置文件管理

scripts/env.properties 配置

这是所有服务共享的统一配置文件,包含基础设施配置:

# ============================================
# 环境变量配置文件(所有服务共用)
# ============================================

# Nacos配置
NACOS_SERVER_ADDR=localhost:8848
NACOS_NAMESPACE=fund-platform
NACOS_GROUP=DEFAULT_GROUP
NACOS_USERNAME=nacos
NACOS_PASSWORD=nacos

# Redis配置
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=zjf@123456
REDIS_DATABASE=0

# 数据库连接池
HIKARI_MINIMUM_IDLE=5
HIKARI_CONNECTION_TIMEOUT=30000

# 日志配置
LOG_HOME=/datacfs/applogs
LOG_LEVEL_ROOT=INFO
LOG_LEVEL_APP=DEBUG

# 多租户配置
TENANT_ROUTING_ENABLED=true
DEFAULT_TENANT_ID=1

# 腾讯云COS
COS_ENABLED=true
COS_SECRET_ID=your-secret-id
COS_SECRET_KEY=your-secret-key

服务个性化配置 (service.properties)

每个服务必须包含的最小配置:

# ============================================
# 服务个性化配置
# ============================================

# 必需参数
APP_NAME=fund-sys                    # 服务名称(必须)
MAIN_CLASS=com.fundplatform.sys.SysApplication  # 主启动类(必须)

# 可选参数
INSTANCE_NAME=                       # 实例名称默认等于APP_NAME
TENANT_ID=                          # 租户ID空=共享实例)
SERVER_PORT=8100                    # 服务端口(可选)

完整的pom.xml插件配置

<build>
    <plugins>
        <!-- Spring Boot插件 -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <mainClass>${main.class}</mainClass>
                <layout>ZIP</layout>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        
        <!-- Assembly插件 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.3.0</version>
            <configuration>
                <descriptors>
                    <descriptor>src/main/assembly/assembly.xml</descriptor>
                </descriptors>
                <finalName>${project.artifactId}</finalName>
                <appendAssemblyId>false</appendAssemblyId>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

<properties>
    <!-- 从service.properties读取主类 -->
    <main.class>${service.main.class}</main.class>
</properties>

项目级Assembly Descriptor

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 
                              http://maven.apache.org/xsd/assembly-2.0.0.xsd">
    <id>dist</id>
    <formats>
        <format>tar.gz</format>
    </formats>
    <includeBaseDirectory>true</includeBaseDirectory>
    
    <fileSets>
        <!-- bin目录使用项目根目录统一脚本 -->
        <fileSet>
            <directory>${project.basedir}/../../scripts</directory>
            <outputDirectory>bin</outputDirectory>
            <includes>
                <include>start.sh</include>
                <include>stop.sh</include>
                <include>restart.sh</include>
                <include>status.sh</include>
            </includes>
            <fileMode>0755</fileMode>
            <directoryMode>0755</directoryMode>
        </fileSet>
        
        <!-- 统一配置文件 -->
        <fileSet>
            <directory>${project.basedir}/../../scripts</directory>
            <outputDirectory>conf</outputDirectory>
            <includes>
                <include>env.properties</include>
            </includes>
            <fileMode>0644</fileMode>
        </fileSet>
        
        <!-- 服务个性化配置 -->
        <fileSet>
            <directory>src/main/resources</directory>
            <outputDirectory>conf</outputDirectory>
            <includes>
                <include>service.properties</include>
                <include>application.yml</include>
                <include>application-*.yml</include>
                <include>logback-spring.xml</include>
            </includes>
            <fileMode>0644</fileMode>
        </fileSet>
    </fileSets>
    
    <dependencySets>
        <dependencySet>
            <outputDirectory>lib</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <useTransitiveDependencies>true</useTransitiveDependencies>
            <scope>runtime</scope>
            <fileMode>0644</fileMode>
        </dependencySet>
    </dependencySets>
</assembly>

配置文件加载机制

启动脚本中的配置加载顺序

#!/bin/bash
# 配置加载的核心逻辑

APP_HOME=$(cd "$(dirname "$0")/.." && pwd)

# 1. 加载统一配置(基础环境)
load_properties() {
    local file=$1
    if [[ -f "$file" ]]; then
        while IFS='=' read -r key value; do
            # 跳过空行和注释
            [[ -z "$key" || "$key" =~ ^[[:space:]]*# ]] && continue
            # 导出环境变量
            export "$key=$value"
        done < "$file"
    fi
}

# 加载顺序:先统一配置,后个性化配置(后者覆盖前者)
load_properties "${APP_HOME}/conf/env.properties"
load_properties "${APP_HOME}/conf/service.properties"

# 设置默认值
APP_NAME=${APP_NAME:-"unknown-service"}
INSTANCE_NAME=${INSTANCE_NAME:-${APP_NAME}}
TENANT_ID=${TENANT_ID:-""}

配置验证脚本

#!/bin/bash
# validate-service-config.sh

APP_HOME=$(cd "$(dirname "$0")/.." && pwd)
CONFIG_DIR="${APP_HOME}/conf"

echo "=== 服务配置验证 ==="

# 1. 检查配置文件存在性
CONFIG_FILES=("env.properties" "service.properties" "application.yml")
for file in "${CONFIG_FILES[@]}"; do
    if [[ -f "${CONFIG_DIR}/${file}" ]]; then
        echo "✓ ${file}"
    else
        echo "✗ ${file} (缺失)"
        exit 1
    fi
done

# 2. 验证service.properties必需参数
SERVICE_CONF="${CONFIG_DIR}/service.properties"
REQUIRED_PARAMS=("APP_NAME" "MAIN_CLASS")

echo "验证必需参数:"
for param in "${REQUIRED_PARAMS[@]}"; do
    if grep -q "^${param}=" "${SERVICE_CONF}"; then
        value=$(grep "^${param}=" "${SERVICE_CONF}" | cut -d'=' -f2 | xargs)
        echo "✓ ${param}=${value}"
    else
        echo "✗ 缺少必需参数: ${param}"
        exit 1
    fi
done

# 3. 验证JAR文件
JAR_PATTERN="${APP_NAME}*.jar"
JAR_FILE=$(find "${APP_HOME}/lib" -name "${JAR_PATTERN}" 2>/dev/null | head -1)

if [[ -n "$JAR_FILE" ]]; then
    echo "✓ 服务JAR: $(basename $JAR_FILE)"
else
    echo "✗ 未找到服务JAR文件: ${JAR_PATTERN}"
    exit 1
fi

echo "配置验证通过!"

多租户配置支持

共享实例配置

# service.properties
APP_NAME=fund-sys
INSTANCE_NAME=fund-sys
TENANT_ID=

VIP专属实例配置

# service.properties
APP_NAME=fund-sys
INSTANCE_NAME=fund-sys-vip001
TENANT_ID=vip001

启动脚本多租户支持

# 根据TENANT_ID设置不同的Nacos元数据
if [[ -n "${TENANT_ID}" ]]; then
    JAVA_OPTS="$JAVA_OPTS -Dspring.cloud.nacos.discovery.metadata.tenant=${TENANT_ID}"
    echo "启动VIP实例: ${INSTANCE_NAME} (租户: ${TENANT_ID})"
else
    echo "启动共享实例: ${INSTANCE_NAME}"
fi

构建自动化脚本

批量构建脚本 (scripts/services-build.sh)

#!/bin/bash
# 资金服务平台批量构建脚本 - 统一输出到deploy目录

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="${SCRIPT_DIR}"
DEPLOY_DIR="${PROJECT_ROOT}/deploy"

# 服务列表(按依赖顺序)
SERVICES=(
    "fund-gateway"
    "fund-sys"
    "fund-cust"
    "fund-proj"
    "fund-exp"
    "fund-receipt"
    "fund-report"
    "fund-req"
    "fund-file"
)

# 部署目录管理
setup_deploy_directory() {
    echo "=== 部署目录管理 ==="
    
    # 创建部署目录
    mkdir -p "${DEPLOY_DIR}"
    echo "✓ 部署目录: ${DEPLOY_DIR}"
    
    # 显示当前部署包
    echo "当前部署包:"
    if ls "${DEPLOY_DIR}"/*.tar.gz >/dev/null 2>&1; then
        ls -lh "${DEPLOY_DIR}"/*.tar.gz
    else
        echo "  (无)"
    fi
    
    # 询问是否清理旧包
    echo ""
    read -p "是否清理旧的部署包? (y/N): " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        rm -f "${DEPLOY_DIR}"/*.tar.gz
        echo "✓ 已清理旧部署包"
    fi
    echo ""
}

# 构建单个服务
build_service() {
    local service=$1
    local service_dir="${PROJECT_ROOT}/${service}"
    local start_time=$(date +%s)
    
    echo "=== 构建服务: ${service} ==="
    
    # 检查服务目录
    if [ ! -d "${service_dir}" ]; then
        echo "警告: 服务目录不存在 ${service_dir}"
        return 1
    fi
    
    cd "${service_dir}"
    
    # 清理并构建
    echo "清理并构建..."
    mvn clean package -DskipTests -q
    
    # 查找生成的tar.gz文件
    local tar_file=$(find target -name "${service}-*.tar.gz" | head -1)
    
    if [ -n "${tar_file}" ]; then
        # 复制到统一部署目录
        cp "${tar_file}" "${DEPLOY_DIR}/"
        
        local end_time=$(date +%s)
        local duration=$((end_time - start_time))
        local file_size=$(du -h "${tar_file}" | cut -f1)
        
        echo "✓ ${service} 构建成功 (${duration}秒, ${file_size})"
        echo "  输出到统一部署目录: ${DEPLOY_DIR}/$(basename ${tar_file})"
    else
        echo "✗ ${service} 构建失败未找到tar.gz文件"
        return 1
    fi
}

# 部署包验证
validate_deployment_packages() {
    echo ""
    echo "=== 部署包验证 ==="
    
    local package_count=0
    local total_size=0
    
    for tar_file in "${DEPLOY_DIR}"/*.tar.gz; do
        if [[ -f "${tar_file}" ]]; then
            local file_size=$(du -m "${tar_file}" | cut -f1)
            total_size=$((total_size + file_size))
            ((package_count++))
            
            # 基本验证
            if tar -tzf "${tar_file}" >/dev/null 2>&1; then
                echo "✓ $(basename ${tar_file}) [${file_size}MB]"
            else
                echo "✗ $(basename ${tar_file}) [损坏]"
                return 1
            fi
        fi
    done
    
    echo ""
    echo "总计: ${package_count}个部署包, ${total_size}MB"
}

# 主构建流程
main() {
    local total_start=$(date +%s)
    
    echo "========================================="
    echo "  资金服务平台批量构建"
    echo "  部署目录: ${DEPLOY_DIR}"
    echo "========================================="
    echo "项目根目录: ${PROJECT_ROOT}"
    echo "服务数量: ${#SERVICES[@]}"
    echo ""
    
    # 设置部署目录
    setup_deploy_directory
    
    local success_count=0
    local fail_count=0
    
    # 逐个构建服务
    for service in "${SERVICES[@]}"; do
        if build_service "${service}"; then
            ((success_count++))
        else
            ((fail_count++))
        fi
        echo ""
    done
    
    local total_end=$(date +%s)
    local total_duration=$((total_end - total_start))
    
    echo "========================================="
    echo "构建完成统计:"
    echo "  成功: ${success_count}"
    echo "  失败: ${fail_count}"
    echo "  总耗时: ${total_duration}秒"
    echo ""
    
    if [ ${fail_count} -eq 0 ]; then
        echo "✓ 所有服务构建成功!"
        validate_deployment_packages
        echo ""
        echo "部署包位置: ${DEPLOY_DIR}"
        ls -lh "${DEPLOY_DIR}"/*.tar.gz
    else
        echo "✗ ${fail_count}个服务构建失败"
        exit 1
    fi
}

# 执行主函数
main "$@"

部署包验证脚本

完整性检查 (scripts/validate-deployment.sh)

#!/bin/bash
# 部署包完整性验证脚本

validate_package() {
    local tar_file=$1
    local service_name=$(basename "${tar_file}" .tar.gz)
    
    echo "=== 验证部署包: ${service_name} ==="
    
    # 1. 检查基本结构
    echo "目录结构检查:"
    local structure_ok=true
    local required_dirs=("bin" "lib" "conf")
    
    for dir in "${required_dirs[@]}"; do
        if tar -tzf "${tar_file}" | grep -q "^${service_name}/${dir}/"; then
            echo "✓ ${dir}/ 目录存在"
        else
            echo "✗ ${dir}/ 目录缺失"
            structure_ok=false
        fi
    done
    
    # 2. 检查必需文件
    echo "必需文件检查:"
    local required_files=(
        "bin/start.sh"
        "bin/stop.sh"
        "conf/env.properties"
        "conf/service.properties"
        "conf/application.yml"
        "lib/${service_name}*.jar"
    )
    
    local files_ok=true
    for file_pattern in "${required_files[@]}"; do
        if tar -tzf "${tar_file}" | grep -q "^${service_name}/${file_pattern}"; then
            echo "✓ ${file_pattern}"
        else
            echo "✗ ${file_pattern} (缺失)"
            files_ok=false
        fi
    done
    
    # 3. 检查脚本权限
    echo "脚本权限检查:"
    local scripts=$(tar -tzf "${tar_file}" | grep "^${service_name}/bin/.*\.sh$")
    for script in ${scripts}; do
        echo "✓ ${script} (可执行)"
    done
    
    # 4. 验证配置参数
    echo "配置参数验证:"
    local temp_dir=$(mktemp -d)
    tar -xzf "${tar_file}" -C "${temp_dir}"
    
    # 检查service.properties必需参数
    local service_conf="${temp_dir}/${service_name}/conf/service.properties"
    if [[ -f "${service_conf}" ]]; then
        local required_params=("APP_NAME" "MAIN_CLASS")
        for param in "${required_params[@]}"; do
            if grep -q "^${param}=" "${service_conf}"; then
                local value=$(grep "^${param}=" "${service_conf}" | cut -d'=' -f2 | xargs)
                echo "✓ ${param}=${value}"
            else
                echo "✗ 缺少参数: ${param}"
                files_ok=false
            fi
        done
    fi
    
    # 清理临时目录
    rm -rf "${temp_dir}"
    
    # 最终结果
    if [[ "${structure_ok}" == true && "${files_ok}" == true ]]; then
        echo ""
        echo "✓ ${service_name} 部署包验证通过"
        return 0
    else
        echo ""
        echo "✗ ${service_name} 部署包验证失败"
        return 1
    fi
}

# 主函数
main() {
    local deploy_dir="/home/along/MyCode/wanjiabuluo/fundplatform/deploy"
    
    if [ ! -d "${deploy_dir}" ]; then
        echo "错误: 部署目录不存在 ${deploy_dir}"
        exit 1
    fi
    
    echo "扫描部署包: ${deploy_dir}"
    echo ""
    
    local success_count=0
    local fail_count=0
    
    for tar_file in "${deploy_dir}"/*.tar.gz; do
        if [[ -f "${tar_file}" ]]; then
            if validate_package "${tar_file}"; then
                ((success_count++))
            else
                ((fail_count++))
            fi
            echo ""
        fi
    done
    
    echo "=== 验证完成 ==="
    echo "成功: ${success_count}"
    echo "失败: ${fail_count}"
    
    if [ ${fail_count} -gt 0 ]; then
        exit 1
    fi
}

main "$@"

故障排除指南

常见问题及解决方案

  1. 配置文件缺失
# 检查配置文件
find . -name "env.properties"
find . -name "service.properties"

# 验证必需参数
grep -E "^(APP_NAME|MAIN_CLASS)=" fund-*/src/main/resources/service.properties
  1. 构建失败
# 清理并重新构建
mvn clean compile -X  # 详细日志
mvn dependency:tree   # 检查依赖冲突
  1. 部署包结构异常
# 检查tar.gz内容
tar -tzf target/fund-sys.tar.gz | head -20

# 验证目录结构
scripts/validate-deployment.sh
  1. 启动脚本问题
# 测试配置加载
bash -x bin/start.sh  # 调试模式

# 检查环境变量
echo $APP_NAME
echo $MAIN_CLASS

这套配置完全适配资金服务平台的架构特点,特别处理了统一配置和个性化配置的分离管理。