Files
starRiverProperty/docs/visitor-floor-policy-implementation-log.md
T
hpd840321 abc690af09 docs: rewrite implementation log as deployment step document
原内容为开发阶段的git操作日志,现重写为面向运维人员的部署实施步骤文档

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-26 09:32:55 +08:00

404 lines
13 KiB
Markdown
Raw 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.
# 租户访客楼层策略 — 部署实施步骤
> **项目**: 星河湾星中星 (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 条广发基金 28Fgf_vstr_policy_guangfa_fund_001x
-- 7 条物业管理 28F+6Fpm_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] 入口日志为 DEBUGinfo.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"}'
# 返回楼层应为 28Fzone_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` |