# 租户访客楼层策略 — 部署实施步骤 > **项目**: 星河湾星中星 (starRiverProperty) > **功能**: 租户访客楼层策略(REPLACE_ALLOWLIST) > **基线版本**: v2.0.17 > **适用环境**: 生产环境(10.0.22.103) --- ## 一、部署概览 ### 1.1 涉及组件 | 组件 | 服务名 | 端口 | 变更类型 | |------|--------|------|---------| | component-organization 服务 | ninca-common-component-organization | 17016 | JAR 升级 + DDL | | 电梯应用 | cw-elevator-application | 18081 | JAR 升级(无配置变更) | ### 1.2 涉及数据库 | 数据库 | IP | 变更类型 | 说明 | |--------|----|---------|------| | `component-organization` | 10.0.22.103 | DDL + DML | 新建策略表 + 种子数据 | | `cw-elevator-application` | 10.0.22.103 | 无 | 仅代码查询,表已废弃 | ### 1.3 发布包 | 发布包 | 构建脚本 | 输出路径 | |--------|---------|---------| | `ninca-common-component-organization-{ver}-xinghewan-{YYYYMMDD}.zip` | `scripts/build/release-component-organization.sh` | `backend/ninca-common-component-organization/releases/` | | `cw-elevator-application-V{ver}.{YYYYMMDD}.zip` | `scripts/build/release-cw-elevator-application.sh` | `backend/cw-elevator-application/releases/` | --- ## 二、前置准备 ### 2.1 数据库全量备份(必需) 在实施任何变更前,对生产数据库服务器(10.0.22.103)执行全库备份。 ```bash # 备份全部数据库(预计 5-10 分钟,3.1 GB) MYSQL_HOST=10.0.22.103 MYSQL_USER=root BACKUP_DIR=/data/backup/$(date +%Y%m%d_%H%M%S) mkdir -p "$BACKUP_DIR" # 获取所有数据库列表(排除系统库) databases=$(mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p \ -e "SHOW DATABASES;" | grep -Ev "^(Database|information_schema|performance_schema|mysql|sys)$") # 逐个备份 for db in $databases; do echo "Backing up $db ..." mysqldump -h "$MYSQL_HOST" -u "$MYSQL_USER" -p \ --single-transaction --routines --triggers --events \ "$db" | gzip > "$BACKUP_DIR/${db}_$(date +%Y%m%d_%H%M%S).sql.gz" done echo "Backup complete: $BACKUP_DIR" ls -lh "$BACKUP_DIR" ``` **备份验证**: ```bash # 检查备份文件完整性 for f in "$BACKUP_DIR"/*.sql.gz; do gzip -t "$f" || echo "CORRUPT: $f" done # 检查 component-organization 备份大小(应有 200MB+) ls -lh "$BACKUP_DIR"/component-organization*.sql.gz ``` ### 2.2 发布包准备 ```bash # 构建 component-org 发布包 cd /path/to/repo bash scripts/build/release-component-organization.sh 2.9.5 # 构建电梯应用发布包 bash scripts/build/release-cw-elevator-application.sh 2.0.17 # 产物确认 ls -lh backend/ninca-common-component-organization/releases/*.zip ls -lh backend/cw-elevator-application/releases/*.zip ``` ### 2.3 当前状态快照 ```bash # 记录当前运行状态 echo "=== 部署前状态快照 ===" > /tmp/pre-deploy-state.txt date >> /tmp/pre-deploy-state.txt # component-org 进程 ps aux | grep component-organization >> /tmp/pre-deploy-state.txt # 电梯应用进程 ps aux | grep cw-elevator-application >> /tmp/pre-deploy-state.txt # 当前策略表状态(应不存在或为空) mysql -h 10.0.22.103 -u root -p component-organization \ -e "SELECT COUNT(*) AS policy_count FROM tenant_visitor_floor_policy;" 2>/dev/null \ || echo "Table not exists (expected)" >> /tmp/pre-deploy-state.txt # 策略日志当前状态 tail -50 logs/component-organization.info.log | grep POLICY \ >> /tmp/pre-deploy-state.txt 2>/dev/null || true ``` --- ## 三、部署步骤 ### Step 1:数据库 DDL — 建表 在 **component-organization** 库创建策略表。 ```bash # 执行建表 DDL mysql -h 10.0.22.103 -u root -p component-organization \ < docs/sql/organization_tenant_visitor_floor_policy.sql ``` **验证**: ```sql SHOW TABLES LIKE 'tenant_visitor_floor_policy'; SHOW CREATE TABLE tenant_visitor_floor_policy; -- 预期: -- policy_type DEFAULT 'REPLACE_ALLOWLIST'(非 INTERSECT_ALLOWLIST) -- 唯一键 uk_org_building (org_id, building_id) -- 索引 idx_org_enabled (org_id, enabled) ``` ### Step 2:数据库 DML — 种子数据 写入广发基金 28F + 物业管理 28F+6F 策略数据。 ```bash # 执行种子数据(幂等,可重复执行) mysql -h 10.0.22.103 -u root -p component-organization \ < docs/sql/organization_tenant_visitor_floor_policy_init_tenants.sql ``` **验证**: ```sql -- 验证数据完整性 SELECT id, org_id, policy_type, allow_zone_ids, remark, enabled FROM tenant_visitor_floor_policy WHERE enabled = 1; -- 预期返回 8 条记录: -- 1 条广发基金 28F(gf_vstr_policy_guangfa_fund_001x) -- 7 条物业管理 28F+6F(pm_6f_vstr_policy_001 ~ 007) -- 验证策略类型 SELECT DISTINCT policy_type FROM tenant_visitor_floor_policy; -- 预期:只有 REPLACE_ALLOWLIST ``` ### Step 3:部署 component-org 服务 ```bash # 1. 传输发布包到目标服务器 scp backend/ninca-common-component-organization/releases/\ ninca-common-component-organization-2.9.5-xinghewan-*.zip \ user@target-server:/opt/cw/component-organization/ # 2. 解压 cd /opt/cw/component-organization unzip ninca-common-component-organization-2.9.5-xinghewan-*.zip cd ninca-common-component-organization-2.9.5-xinghewan-*/ # 3. 替换配置(如需要) # 确认 bootstrap.properties / application.properties 与现网一致 # 4. 停止旧服务 systemctl stop ninca-common-component-organization # 或 kill 进程 # ps aux | grep component-organization | grep -v grep | awk '{print $2}' | xargs kill # 5. 确认旧进程已退出 ps aux | grep component-organization # 6. 启动新服务 bash start.sh # 或 systemctl start ninca-common-component-organization # 7. 检查启动日志 tail -f logs/component-organization.info.log # 预期: # - 无 Bean 冲突异常 # - 无 ResourceBundle WARN # - 端口 17016 监听正常 ``` **启动验证**: ```bash # 检查端口 ss -tlnp | grep 17016 # 健康检查 curl -s http://127.0.0.1:17016/health # 测试 detail 接口(含策略) curl -X POST http://127.0.0.1:17016/component/person/detail \ -d '{"personId":"1072908835884208128","businessId":"2524639890ba4f2cba9ba1a4eeaa4015"}' # 检查策略日志 grep 'POLICY-HIT\|POLICY-RESULT' logs/component-organization.info.log ``` ### Step 4:部署电梯应用(如需要) ```bash # 如果电梯应用 JAR 也有更新: scp backend/cw-elevator-application/releases/\ cw-elevator-application-V*.zip \ user@target-server:/opt/cw/elevator/ cd /opt/cw/elevator unzip cw-elevator-application-V*.zip cd cw-elevator-application-V*/ # 停止旧服务 → 替换 JAR → 启动 bash stop.sh cp *.jar deploy/v2-maven/ bash start.sh ``` **注意**:如果仅变更策略数据(SQL 种子),电梯应用**无需重启**。策略查询通过 Feign → component-org 实时获取。 ### Step 5:日志配置确认 ```bash # 确认策略日志已正确输出 grep -E 'POLICY-HIT|POLICY-MISS|POLICY-FALLBACK|POLICY-EMPTY' \ logs/component-organization.info.log # 确认无 ResourceBundle WARN grep 'ResourceBundle' logs/component-organization.info.log || echo "PASS: 无 ResourceBundle WARN" # 确认 [POLICY] 入口日志为 DEBUG(info.log 不应出现 POLICY entry) grep '\[POLICY\] entry' logs/component-organization.info.log || echo "PASS: 无 POLICY entry INFO 日志" ``` --- ## 四、功能验证 ### 4.1 策略命中验证 ```bash # 测试广发基金访客楼层 curl -X POST http://127.0.0.1:17016/elevator/person/add/visitor \ -d '{"personId":"1072908835884208128", "businessId":"2524639890ba4f2cba9ba1a4eeaa4015", "visitorName":"test_visitor_gf"}' # 返回楼层应为 28F(zone_id: 605560545117995008) # 测试物业管理访客楼层 curl -X POST http://127.0.0.1:17016/elevator/person/add/visitor \ -d '{"personId":"another_person_id", "businessId":"another_business_id", "visitorName":"test_visitor_pm"}' # 返回楼层应为 28F + 6F ``` ### 4.2 无策略兜底验证 ```bash # 使用无策略配置的组织人员测试 curl -X POST http://127.0.0.1:17016/component/person/detail \ -d '{"personId":"person_id_without_policy", "businessId":"business_id_without_policy"}' # 返回 floorList 应保持 listByImageId 原始值(未被替换) ``` ### 4.3 异常容错验证 ```bash # 模拟策略表不可用(临时重命名) # mysql -h 10.0.22.103 -u root -p component-organization \ # -e "RENAME TABLE tenant_visitor_floor_policy TO tenant_visitor_floor_policy_bak;" # 测试 detail 仍正常返回 curl -X POST http://127.0.0.1:17016/component/person/detail \ -d '{"personId":"1072908835884208128", "businessId":"2524639890ba4f2cba9ba1a4eeaa4015"}' # 预期:正常返回数据,floorList 为原始值 # 日志应有 POLICY-FALLBACK WARN # 恢复策略表 # mysql -h 10.0.22.103 -u root -p component-organization \ # -e "RENAME TABLE tenant_visitor_floor_policy_bak TO tenant_visitor_floor_policy;" ``` ### 4.4 验收检查表 | # | 检查项 | 预期 | 结果 | |---|--------|------|------| | 1 | 策略表已创建 | `SHOW TABLES` 显示 `tenant_visitor_floor_policy` | □ 通过 □ 不通过 | | 2 | 广发基金 28F 策略 | 查表有 `gf_vstr_policy_guangfa_fund_001x` | □ 通过 □ 不通过 | | 3 | 物业 7 条 28F+6F 策略 | 查表有 `pm_6f_vstr_policy_001` ~ `007` | □ 通过 □ 不通过 | | 4 | 策略类型全为 REPLACE_ALLOWLIST | `SELECT DISTINCT policy_type` = 1 种 | □ 通过 □ 不通过 | | 5 | 广发访客 → 28F | 访客创建后楼层为 28F | □ 通过 □ 不通过 | | 6 | 物业访客 → 28F+6F | 访客创建后楼层为 28F+6F | □ 通过 □ 不通过 | | 7 | 无策略组织 → 原始楼层 | 不受影响 | □ 通过 □ 不通过 | | 8 | 策略停用 (enabled=0) → 不生效 | 停用后楼层不被替换 | □ 通过 □ 不通过 | | 9 | 策略查询异常 → 不阻断 | 表不可用时 detail 正常返回 | □ 通过 □ 不通过 | | 10 | component-org 启动正常 | 端口 17016 监听,无 Bean 冲突 | □ 通过 □ 不通过 | | 11 | POLICY-HIT 有日志 | `grep 'POLICY-HIT' info.log` 有输出 | □ 通过 □ 不通过 | | 12 | 无 ResourceBundle WARN | `grep ResourceBundle` 无输出 | □ 通过 □ 不通过 | --- ## 五、回滚方案 ### 5.1 快速回滚(停用策略) 无需重启服务,仅需 SQL。 ```bash # 停用所有策略(立即生效) mysql -h 10.0.22.103 -u root -p component-organization \ -e "UPDATE tenant_visitor_floor_policy SET enabled=0 WHERE enabled=1;" # 验证 mysql -h 10.0.22.103 -u root -p component-organization \ -e "SELECT COUNT(*) AS active_policies FROM tenant_visitor_floor_policy WHERE enabled=1;" # 预期:0 # 恢复策略(重新启用) mysql -h 10.0.22.103 -u root -p component-organization \ -e "UPDATE tenant_visitor_floor_policy SET enabled=1;" ``` ### 5.2 服务回滚(JAR 回退) ```bash # 1. 停止服务 systemctl stop ninca-common-component-organization # 2. 备份新 JAR mv ninca-common-component-organization-2.9.5.jar \ ninca-common-component-organization-2.9.5.jar.rollback # 3. 恢复旧 JAR cp /backup/ninca-common-component-organization-previous.jar \ ninca-common-component-organization-2.9.5.jar # 4. 启动服务 systemctl start ninca-common-component-organization # 5. 验证 tail -f logs/component-organization.info.log ``` ### 5.3 全量数据库恢复 仅在 DDL 执行后出现数据损坏时使用。 ```bash # 使用部署前备份的全量 SQL RESTORE_FILE=/data/backup/YYYYMMDD_HHMMSS/component-organization_YYYYMMDD_HHMMSS.sql.gz # 恢复 component-organization 库 zcat "$RESTORE_FILE" | mysql -h 10.0.22.103 -u root -p component-organization # 验证恢复后策略表应不存在(或为旧状态) mysql -h 10.0.22.103 -u root -p component-organization \ -e "SHOW TABLES LIKE 'tenant_visitor_floor_policy';" ``` --- ## 六、注意事项 1. **DDL 幂等性**:建表 SQL 使用 `CREATE TABLE IF NOT EXISTS`,种子 SQL 使用 `ON DUPLICATE KEY UPDATE`,重复执行不会报错。 2. **电梯侧策略表已废弃**:`cw-elevator-application` 库的 `tenant_visitor_floor_policy` 表 V2 不再查询,仅供历史参考。 3. **唯一策略维护点**:所有策略变更在 **component-organization** 库执行。 4. **Graceful Shutdown**:component-org 服务配置了 30s 排空等待,停止服务时在途请求可正常完成。 5. **JDK 版本**:所有服务必须使用 JDK 8。 6. **日志级别**:[POLICY] 入口日志为 DEBUG 级别,正常运行时 `info.log` 不会出现 `POLICY entry`。 --- ## 附录:关键命令速查 | 操作 | 命令 | |------|------| | 建表 | `mysql -h 10.0.22.103 -u root -p component-organization < organization_tenant_visitor_floor_policy.sql` | | 种子数据 | `mysql -h 10.0.22.103 -u root -p component-organization < organization_tenant_visitor_floor_policy_init_tenants.sql` | | 查策略 | `SELECT id, org_id, policy_type, allow_zone_ids, remark FROM tenant_visitor_floor_policy WHERE enabled=1;` | | 停用策略 | `UPDATE tenant_visitor_floor_policy SET enabled=0;` | | 查策略命中 | `grep 'POLICY-HIT' logs/component-organization.info.log` | | 查策略回退 | `grep 'POLICY-FALLBACK' logs/component-organization.info.log` | | 服务状态 | `ss -tlnp \| grep 17016` | | 健康检查 | `curl http://127.0.0.1:17016/health` | | 全库备份 | `mysqldump --single-transaction ... \| gzip > backup.sql.gz` |