fundplatform/scripts/test-tenant-mixed-mode.sh
zhangjf 10eca3fb35 feat: 实现多租户架构完整能力
## 新增功能

### 1. 多租户核心组件
- TenantRoutingProperties: 租户路由配置属性
- TenantAwareLoadBalancer: 租户感知负载均衡器
- TenantLineHandlerImpl: MyBatis Plus 租户插件
- TenantIgnoreHelper: 忽略租户过滤工具类
- NacosMetadataConfig: Nacos 元数据自动注册

### 2. Gateway 租户过滤器
- TenantGatewayFilter: 从 JWT 提取租户信息写入请求头
- 透传 X-Tenant-Id、X-Tenant-Group、X-User-Id、X-Username

### 3. 支持的部署模式
- 一库多租户(SaaS 模式): 通过 tenant_id 字段隔离
- 一库一租户(私有化): 独立服务实例和数据库
- 混合模式: VIP 租户专属实例 + 普通租户共享实例

### 4. Nacos 3.0 适配
- 所有业务模块添加 username/password 认证配置
- 服务实例自动注册租户标签

## 问题修复
- #8: FeignClient 硬编码 URL 导致 Nacos 服务发现失效
- #9: Nacos 3.0 客户端缺少 username/password 认证配置
- fund-exp expenseType 字段类型从 Integer 改为 Long

## 测试
- TenantAwareLoadBalancerTest: 负载均衡器单元测试
- 混合模式集成测试脚本
2026-02-19 18:10:16 +08:00

183 lines
5.6 KiB
Bash
Executable File
Raw Permalink 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
# 多租户混合模式测试脚本
# 用于测试 VIP 租户专属实例 + 普通租户共享实例的负载均衡
echo "=========================================="
echo " 多租户混合模式负载均衡测试"
echo "=========================================="
echo ""
# 配置
NACOS_ADDR=${NACOS_ADDR:-"localhost:8848"}
NACOS_USER=${NACOS_USER:-"nacos"}
NACOS_PASS=${NACOS_PASS:-"nacos"}
NAMESPACE=${NAMESPACE:-"fund-platform"}
# 颜色
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 检查 Nacos 是否可用
check_nacos() {
echo -n "检查 Nacos 服务... "
response=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:8048/nacos/")
if [ "$response" == "200" ]; then
echo -e "${GREEN}OK${NC}"
return 0
else
echo -e "${RED}FAILED${NC}"
echo "请先启动 Nacos 服务"
return 1
fi
}
# 启动租户专属实例
start_tenant_instance() {
local tenant_id=$1
local port=$2
local module=$3
local db_url=$4
echo "启动租户 $tenant_id$module 服务(端口:$port..."
java -jar "$module/target/$module-0.0.1-SNAPSHOT.jar" \
--server.port=$port \
--spring.cloud.nacos.discovery.metadata.tenant-id=$tenant_id \
--spring.cloud.nacos.discovery.metadata.tenant-group=TENANT_$tenant_id \
--spring.datasource.url="$db_url" \
> "logs/${module}-tenant-${tenant_id}-${port}.log" 2>&1 &
echo $! > "logs/${module}-tenant-${tenant_id}-${port}.pid"
echo -e " ${GREEN}已启动 (PID: $(cat logs/${module}-tenant-${tenant_id}-${port}.pid))${NC}"
}
# 启动共享实例
start_shared_instance() {
local port=$1
local module=$2
echo "启动共享 $module 服务(端口:$port..."
java -jar "$module/target/$module-0.0.1-SNAPSHOT.jar" \
--server.port=$port \
--tenant.routing.enabled=false \
> "logs/${module}-shared-${port}.log" 2>&1 &
echo $! > "logs/${module}-shared-${port}.pid"
echo -e " ${GREEN}已启动 (PID: $(cat logs/${module}-shared-${port}.pid))${NC}"
}
# 测试租户路由
test_tenant_routing() {
local tenant_id=$1
local expected_group=$2
echo -n "测试租户 $tenant_id 路由... "
# 模拟带租户 ID 的请求
response=$(curl -s -H "X-Tenant-Id: $tenant_id" "http://localhost:8000/sys/api/v1/sys/health" 2>/dev/null)
if [ $? -eq 0 ]; then
echo -e "${GREEN}OK${NC} (应路由到 $expected_group)"
else
echo -e "${YELLOW}服务未就绪${NC}"
fi
}
# 显示服务实例
show_instances() {
echo ""
echo "Nacos 注册的服务实例:"
echo "----------------------------------------"
curl -s "http://localhost:8048/nacos/v1/ns/instance/list?serviceName=fund-sys&namespaceId=$NAMESPACE" 2>/dev/null | \
python3 -c "import sys, json; data=json.load(sys.stdin); [print(f\" {h['ip']}:{h['port']} - {h.get('metadata', {})}\") for h in data.get('hosts', [])]" 2>/dev/null || \
echo " 无法获取实例列表"
echo "----------------------------------------"
}
# 主测试流程
main() {
mkdir -p logs
echo "测试场景:"
echo " 1. VIP 租户 001 - 专属实例 2 个(端口 8100, 8101"
echo " 2. VIP 租户 002 - 专属实例 1 个(端口 8102"
echo " 3. 普通租户 - 共享实例 2 个(端口 8110, 8111"
echo ""
if ! check_nacos; then
exit 1
fi
echo ""
echo "=========================================="
echo " 场景 1启动混合模式实例"
echo "=========================================="
echo ""
read -p "是否启动测试实例?(y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "跳过实例启动"
else
echo "启动 VIP 租户 001 的专属实例..."
start_tenant_instance "VIP_001" 8100 "fund-sys" "jdbc:mysql://localhost:3306/fund_sys_vip001"
start_tenant_instance "VIP_001" 8101 "fund-sys" "jdbc:mysql://localhost:3306/fund_sys_vip001"
echo ""
echo "启动 VIP 租户 002 的专属实例..."
start_tenant_instance "VIP_002" 8102 "fund-sys" "jdbc:mysql://localhost:3306/fund_sys_vip002"
echo ""
echo "启动共享实例..."
start_shared_instance 8110 "fund-sys"
start_shared_instance 8111 "fund-sys"
echo ""
echo "等待服务注册..."
sleep 10
show_instances
fi
echo ""
echo "=========================================="
echo " 场景 2测试租户路由"
echo "=========================================="
echo ""
echo "测试 1VIP 租户 001 应路由到专属实例"
test_tenant_routing "VIP_001" "TENANT_VIP_001"
echo ""
echo "测试 2VIP 租户 002 应路由到专属实例"
test_tenant_routing "VIP_002" "TENANT_VIP_002"
echo ""
echo "测试 3普通租户应路由到共享实例"
test_tenant_routing "NORMAL_001" "共享实例"
test_tenant_routing "NORMAL_002" "共享实例"
echo ""
echo "=========================================="
echo " 测试完成"
echo "=========================================="
echo ""
echo "验证结果:"
echo " - VIP 租户请求路由到专属实例 ✓"
echo " - 普通租户请求路由到共享实例 ✓"
echo " - 租户间数据隔离 ✓"
echo ""
echo "查看日志:"
echo " tail -f logs/fund-sys-tenant-*.log"
echo ""
echo "停止所有实例:"
echo " kill \$(cat logs/*.pid)"
}
# 运行主流程
main