Files
starRiverProperty/docs/superpowers/specs/2026-05-10-component-org-log-analysis.md
T

352 lines
16 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.
# component-organization.info.log 全量分析 & 策略频繁调用根因分析
**日期**: 2026-05-10
**日志范围**: 12:41:32 ~ 13:18:38 (37 分钟)
**分支**: feature/guangfa-28f-hardcoded
**数据库**: 10.0.22.103 / cloudwalk / component-organization
---
## 一、日志概览
```
文件: logs/component-organization.info.log
大小: 26MB
行数: 106,372
TraceId: 9,848 个
服务端口: 17016
```
### 日志构成
```
████████████████████████████░░░░░ 84.2% 设备同步 (89,531 行)
██████████░░░░░░░░░░░░░░░░░░░░░░ 29.9% WARN (31,800 行)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0.06% 用户业务 detail() 调用 (64 行)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0.02% ERROR (20 行)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0.01% POLICY 命中 (12 行)
```
---
## 二、服务启动时间线
```
12:41:32 首个请求到达(device updatePerson
12:41:42 Quartz 调度器启动
12:42:07 Hystrix 初始化完成
12:44:07 jasypt 加密引导
12:44:09 Redis Lua 脚本 Bean 覆盖(9 个)
12:44:27 Controller 映射注册 /component/person/listPerson
12:46:27 首个业务 detail() 调用(距启动 ~5 分钟)
13:18:38 最后一条日志(图库同步失败 WARN)
```
---
## 三、业务调用完整时间线(36 次 detail 调用)
### 3.1 按调用方来源分类
`POST /component/person/detail` 被以下 **7 个调用方** 消费:
| # | 调用方 | 代码位置 | 调用场景 | 是否需要策略 |
|---|--------|---------|---------|-------------|
| 1 | **前端访客邀约页** | 通过 `PersonController.detail()` | 初始化可选择楼层 | **✅ 需要** |
| 2 | **前端人员管理** | 通过 `PersonController.detail()` | 人员详情查看 | ❌ 不需要 |
| 3 | **elevator addVisitor UC-01** | `PersonRuleServiceImpl:175` | 一键派梯,需要 floorList | **✅ 需要** |
| 4 | **elevator addVisitor UC-02** | `PersonRuleServiceImpl:175` | 仅校验被访人存在 | ❌ 不需要(不用 floorList) |
| 5 | **CRK 访客注册** | `VisitorRegisterServiceImpl:330,648` | 访客登记 | **✅ 需要** |
| 6 | **CRK 门禁识别记录** | `AcsRecogRecordServiceImpl:86` | 识别记录,仅需人员信息 | ❌ 不需要 |
| 7 | **电梯设备/记录** | `AcsElevatorDeviceServiceImpl` 等 | 设备同步 | ❌ 不需要 |
### 3.2 日志中的调用时序
```
12:46:27 detail personId=1099676120751034368 [MFG鼎鸿/613] 4 zones ✗ 未命中
12:46:36 detail personId=833276118323793920 [大地保险/办公室] 3 zones ✗ 未命中
12:48:44 detail personId=730473849711333376 [行政人事部/陕西巨丰] 5 zones ✗ 未命中
12:48:50 detail personId=783987999653621760 [陕西巨丰/业务部] 2 zones ✗ 未命中
12:49:11 detail personId=783987999653621760 [同一人 21秒后再查] 2 zones ✗ 未命中
12:51:22 detail personId=1032218423083470848 陈晶丽 [外包+物管] 38 zones ★ 命中 → 6F
12:53:31 detail personId=903269751508242432 [陕西巨丰/业务部] 2 zones ✗ 未命中
12:56:13 detail personId=1087053273767612416 [612/MFG鼎鸿] 4 zones ✗ 未命中
12:56:25 detail personId=1071436837510660096 [金辉华集团/工程中心] 2 zones ✗ 未命中
12:56:56 detail personId=1087053273767612416 [同一人 43秒后再查] 4 zones ✗ 未命中
12:58:18 detail personId=1028610903966322688 [投资助理/陕西巨丰] 2 zones ✗ 未命中
12:59:55 detail personId=805732141303721984 刘光林 [厨房+物管] 5 zones ★ 命中 → 6F
12:59:59 detail personId=805732141303721984 [同一人 4秒后再查] 5 zones ★ 命中 → 6F
13:00:14 detail personId=1105585180195930112 [仅 1 zone] 1 zone (无策略检查)
13:01:42 detail personId=775326439246499840 [陕西巨丰/业务部] 2 zones ✗ 未命中
13:02:20 detail personId=992819015204597760 雷恒豫 [外包+物管] 38 zones ★ 命中 → 6F
13:02:24 detail personId=901059320052314112 [财务/陕西巨丰] 2 zones ✗ 未命中
13:02:26 detail personId=1018452759471689728 [新媒体/陕西巨丰] 4 zones ✗ 未命中
13:03:06 detail personId=1032604140250959872 冯水英 [环境部+物管] 38 zones ★ 命中 → 6F
13:03:08 detail personId=964199538912989184 戚浩 [外包+物管] 38 zones ★ 命中 → 6F
13:03:25 detail personId=721734719120691200 覃永杰 [保安部+物管] 31 zones ★ 命中 → 6F
13:03:29 detail personId=721734719120691200 [4秒后再查] 31 zones ★ 命中 → 6F ⚠️
13:03:33 detail personId=721734719120691200 [又4秒后再查] 31 zones ★ 命中 → 6F ⚠️
13:03:33 detail personId=770218949916094464 [陕西巨丰/业务部] 2 zones ✗ 未命中
13:03:44 detail personId=721734719120691200 [第4次,11秒后再查] 31 zones ★ 命中 → 6F ⚠️
13:04:09 detail personId=957214640516231168 [新媒体/陕西巨丰] 4 zones ✗ 未命中
13:04:41 detail personId=906237696010194944 [陕西巨丰/大客户部] 2 zones ✗ 未命中
13:05:03 detail personId=771809951973847040 [新媒体/陕西巨丰] 4 zones ✗ 未命中
13:06:13 detail personId=1030066143429201920 [新媒体/陕西巨丰] 6 zones ✗ 未命中
13:07:56 detail personId=770218949916094464 [陕西巨丰/业务部] 2 zones ✗ 未命中
13:09:20 detail personId=1105554183521812480 [仅 1 zone] 1 zone (无策略检查)
13:10:28 detail personId=1101592364922802176 [MFG鼎鸿/613] 4 zones ✗ 未命中
13:13:41 detail personId=605578568533016576 [大地保险] 3 zones ✗ 未命中
13:13:54 detail personId=605578568533016576 [13秒后再查] 3 zones ✗ 未命中
13:13:54 detail personId=992819015204597760 雷恒豫 [外包+物管] 38 zones ★ 命中 → 6F
13:17:25 detail personId=1079804406034599936 [最后一条] 4 zones (无策略检查)
```
### 3.3 高频重复查询分析
```
覃永杰 (721734719120691200): 19秒内查询 4 次
13:03:25 → 13:03:29 (4秒间隔) → 13:03:33 (4秒间隔) → 13:03:44 (11秒间隔)
判断: 前端批量操作(连续打开多人详情)或页面轮询
刘光林 (805732141303721984): 4秒内查询 2 次
12:59:55 → 12:59:59
判断: addVisitor 阶段1 + 前端详情页并发请求
雷恒豫 (992819015204597760): 12分钟内查询 2 次
13:02:20 → 13:13:54
判断: 两次独立操作
```
---
## 四、策略频繁调用的根因分析
### 4.1 问题表述
**用户原意**: 租户访客楼层策略(`TenantVisitorFloorPolicyService`)只应在「访客邀约初始化页面」触发,用于确定被访人的可选楼层列表。
**实际情况**: 策略在 **36 次 detail() 调用** 中被触发了 **24 次**(12 次额外命中做了楼层替换),但其中只有部分来自访客邀约场景。
### 4.2 根因:`detail()` 是多消费者通用 API,策略代码无条件嵌入
```
POST /component/person/detail
┌───────────────────────────────┐
│ ImgPersonServiceImpl.detail() │
│ L670-672: │
│ tenantVisitorFloorPolicy │
│ Service.replacementZoneIds │
│ IfPolicyActive(orgIds) ← 无条件触发!
└───────────────────────────────┘
┌───────────────────┼───────────────────┐
│ │ │
访客邀约页 ✅ 人员管理 ❌ addVisitor
(需要策略) (不需要) UC-02 ❌
(不消费 floorList)
```
### 4.3 所有 detail() 调用方一览
```
personService.detail() 的 Feign 消费者:
1. PersonController.detail() ← 前端 HTTP 入口
├─ 访客邀约页初始化 ✅ 策略必需
└─ 人员管理/详情查看 ❌ 策略无意义(但无法区分)
2. PersonRuleServiceImpl.addVisitor() ← 电梯侧
├─ UC-01(一键派梯) ✅ 需要 floorList
└─ UC-02(调用方指定楼层) ❌ floorList 不被消费(L193 直接取 param.floorIds
3. VisitorRegisterServiceImpl ← CRK 访客
├─ L330 访客登记 ✅ 可能涉及楼层选择
└─ L648 访客登记 ✅ 同上
4. AcsRecogRecordServiceImpl:86 ← CRK 门禁识别
└─ 仅需人员信息 ❌ 完全不涉及楼层
```
### 4.4 为什么设计如此
设计文档 [2026-05-06-tenant-visitor-policy-organization-implementation.md](./2026-05-06-tenant-visitor-policy-organization-implementation.md) 明确规定:
> **floorList 唯一主路径**:获取 `PersonResult.floorList`**必须**调用 `PersonService.detail`
> **业务约定**:凡调用方需消费「被访人可派梯/可邀约访问的楼层集合」,必须走 `PersonService.detail`
这一设计将 `detail()` 作为 **floorList 的权威来源**,策略替代自然应在 `detail()` 内完成。但设计未区分「需要 floorList 的调用方」和「仅需人员信息的调用方」——`detail()` 本就同时承担这两种职责。
### 4.5 策略命中统计
| 目标 orgId | 组织名 | 命中次数 | 限制楼层 | 备注 |
|-----------|--------|---------|---------|------|
| `f216235e...` | 星中心物业管理公司 | 12 | 6F | 物业内部人员被查询 |
| `488b8ad0...` | [28-38F]广发基金 | 0 | 28F | 日志期间无人查询广发人员 |
**24 次未命中** 的 detail() 调用中,大部分是陕西巨丰投资 (a5585cb) 的人员——该组织无策略配置,但仍然触发了 `tenant_visitor_floor_policy` 表的 SELECT 查询(一次 DB 查询 + 空结果集)。
### 4.6 性能影响评估
```
单次 detail() 调用链路:
DB: cw_is_person (必选)
DB: cw_is_person_organization_ref (必选)
DB: cw_is_person_label_ref (必选)
Feign: elevatorFeignClient.listByImageId (必选, 跨服务调用)
DB: tenant_visitor_floor_policy (★ 策略查询, 每次 1 次 SELECT)
WHERE org_id=? AND enabled=1 LIMIT 1
→ 对每个 orgId 执行,命中即停止遍历
```
- 策略查询是基于 `org_id` 的索引查询(`idx_org_enabled`),单次耗时 < 5ms
- 当前日志中 1次/分钟 的频率**无性能问题**
- 但若 `detail()` 被大量并发调用(如批量操作、定时任务),会产生 N×orgCount 次 DB 查询
---
## 五、异常与风险
### 5.1 设备同步 WARN (31,800 条)
```
"查询设备[xxx]失败" (DevicePersonSyncManager:164)
TOP 5 失败设备:
cbbd0da12a9247409cc272e1c365698f 180 次
508d126a19554746a46931afcc5ec9e3 180 次
ca9d9689c8fe4ccf89eba82a9c9df4b4 120 次
f4765e409ffd4705a2639eb41c5251c7 115 次
7a4b5acc463d465ba4550db4939dac19 105 次
原因: 设备侧有注册,组织库中无对应设备 → 每次同步周期都触发查询失败
影响: 日志膨胀(84% 为设备同步日志),掩盖真实业务问题
建议: 清理数据库中不存在的设备记录,或对已知失败设备做静默处理
```
### 5.2 Feign 调用失败 (11 次 ERROR)
```
"call AggDeviceImageStoreFeignClient sync device imageStore failed"
(Hystrix fallback, 分布在 12:49 ~ 13:18)
间隔: 约 1-2 分钟一次
原因: cwos-portal 服务不可达或超时
影响: 图库同步中断,但不影响人员查询
```
### 5.3 图库添加人脸失败 (5 次 ERROR)
```
"图库[c8c67225]添加人脸[1690239736450007040]异常"
"图库[7a83a5d2]添加人脸[1611164976657559552]异常" × 4
集中在 13:06~13:07,为批量操作失败
```
---
## 六、策略优化建议
### 方案 A:添加调用上下文标志(推荐,最小变更)
`DetailImgPersonParam``CloudwalkCallContext` 中添加 `skipFloorPolicy` 字段:
```java
// ImgPersonServiceImpl.detail() L670 修改为:
if (!Boolean.TRUE.equals(param.getSkipFloorPolicy())) {
Optional<List<String>> replacementFloors =
this.tenantVisitorFloorPolicyService
.replacementZoneIdsIfPolicyActive(result.getOrganizationIds());
// ... 现有替换逻辑
}
```
**优点**: 调用方显式控制,不破坏现有契约
**缺点**: 需要所有「不需要策略」的调用方传参(addVisitor UC-02、门禁识别、人员管理等)
### 方案 B:策略仅在 isVisitor 场景触发
```java
// 仅在访客相关场景触发策略
if (Boolean.TRUE.equals(param.getIsVisitor())) {
// 策略检查
}
```
**优点**: 改动最小,一行条件判断
**缺点**: isVisitor 可能不是当前 detail() 的必有参数
### 方案 C:保持现状(设计意图)
按照设计文档,`detail()` 是 floorList 的**权威来源**,策略嵌入是**有意为之**。当前 ~1次/分钟 的调用频率下,额外的 DB 查询成本可忽略。
**优点**: 零改动
**缺点**: 语义不精确,所有 detail() 消费者都触发策略查询
---
## 七、数据库查询结果附录
### 7.1 策略表全量
```sql
SELECT p.id, p.org_id, o.NAME, p.allow_zone_ids, p.remark
FROM tenant_visitor_floor_policy p
LEFT JOIN cw_is_organization o ON p.org_id = o.ID
WHERE p.enabled=1;
```
| policyId | org_name | allow_zone_ids | 限制楼层 |
|----------|---------|---------------|---------|
| pm_6f_vstr_policy_006 | 星中心物管公司 | ["605560541473144832"] | 6F |
| pm_6f_vstr_policy_001 | 星河湾物业管理有限公司 | ["605560541473144832"] | 6F |
| pm_6f_vstr_policy_005 | 星中心物业服务中心 | ["605560541473144832"] | 6F |
| pm_6f_vstr_policy_003 | 星河湾物管公司 | ["605560541473144832"] | 6F |
| pm_6f_vstr_policy_007 | 物业管理总部 | ["605560541473144832"] | 6F |
| pm_6f_vstr_policy_004 | **星中心物业管理公司** | ["605560541473144832"] | **6F** ← 日志命中 |
| pm_6f_vstr_policy_002 | 星河湾物业管理公司 | ["605560541473144832"] | 6F |
| gf_vstr_policy_guangfa_fund_001x | [28-38F]广发基金管理有限公司 | ["605560545117995008"] | 28F |
| demo_vstr_policy_001 | 演示公司 | ["605560545117995008"] | 28F |
### 7.2 楼层编码对照
```
zone_id=605560540432957440 code=0x01 → 1F (首层)
zone_id=605560541473144832 code=0x06 → 6F ★ 物业策略目标
zone_id=605560545117995008 code=0x1C → 28F ★ 广发基金策略目标
```
### 7.3 关键组织节点
```
f216235e54ca42bfa0379e69b3754aff = 星中心物业管理公司 (PARENT_ORG)
├── 348328d755624b3491cd307a3109f36a = 星中心物管公司
├── b39c54d13fe94abe84bfa8d527db4392 = 星中心保安部
├── f113340e671648338eb83fc643cfa94d = 星中心环境管理部
│ └── 8498d4a56f07494ca604789d23fc18f6 = 星中心环境部外包人员
└── df573ae4b98f4be092d524b760bd5c40 = 星景厨房
a5585cb03764490c915ee807aaa13ef3 = 陕西巨丰投资资讯有限责任公司广州分公司
├── b3b5fe629baf45b29a1eb6ed8e7126d8 = 业务部
├── 363742435e3f4dc1b4626819e8637de2 = 行政人事部
├── 4758f34c67364c4c8f6f6c8eb9a4af13 = 新媒体
├── 480bd6c8b49b49568f7a5ee07331a084 = 投资助理
├── 768aa5ef294d4fdc979e1c5a37cb87e7 = 财务/数据/推广
└── e84e681fa6c8463c90f70082cd4bed77 = 大客户服务部
488b8ad049bb43408a6fbcc50bcb89ac = [28-38F]广发基金管理有限公司 (有策略但未被查询)
```
---
## 八、总结
1. **日志主体是设备同步**(84.2%),用户业务调用仅占 0.06%
2. **策略调用频率**: 36 次/37 分钟 ≈ 1 次/分钟,频率不高但覆盖所有 detail() 调用方
3. **根因**: `detail()` 是 floorList 的权威来源(设计意图),策略嵌入是**有意为之**;但 detail() 被 7+ 个不同调用方消费,其中仅 3 个需要策略
4. **是否可以优化**: 可以,但需要改动调用方契约(添加 skip 标志)或在 detail() 内根据业务特征判断。当前频率下保持现状是可接受的
5. **31,800 条 WARN**: 设备同步失败是主要噪音源,建议清理不存在设备的记录