feat: 实现Redis集成与Kafka消息处理优化
- 新增Redis集成模块,支持心跳写入与控制台日志队列 - 优化Kafka消费者实现,支持多实例与自动重连 - 改进消息处理器,支持批量处理与多层解码 - 更新数据库表结构,调整字段类型与约束 - 添加Redis与Kafka的配置项和环境变量支持 - 补充测试用例和文档说明
This commit is contained in:
@@ -32,12 +32,12 @@
|
||||
| pms_state | int2 | 是 | PMS 状态(枚举待定) |
|
||||
| carbon_state | int2 | 是 | 碳控状态(枚举待定) |
|
||||
| device_count | int2 | 是 | 设备数量/上报设备数量(语义待确认) |
|
||||
| comm_seq | int2 | 是 | 通讯序号(语义待确认) |
|
||||
| comm_seq | int4 | 是 | 通讯序号(语义待确认) |
|
||||
| extra | jsonb | 否 | 可扩展字段:电参/空调状态/版本/来源等 |
|
||||
|
||||
### 2.2 约束
|
||||
- 所有必填字段:`NOT NULL`
|
||||
- `ip`:使用 `inet` 类型(天然校验 IPv4/IPv6 格式)
|
||||
- `ip`:使用 `varchar(21)`,用于存储 `IP:PORT`(IPv4)
|
||||
- 各 `int2/int4`:当前脚本采用“非负 + 上界”CHECK(避免枚举未来扩展造成写入失败)
|
||||
- 如需更强的枚举约束,建议在确认枚举标准后改为 `IN (...)` 或 `BETWEEN` 更小范围。
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
本文档说明数据产生者需要往 Kafka 队列推送的数据结构与推送方式。
|
||||
|
||||
## 1. Topic 与编码
|
||||
- Topic:默认 `bls-heartbeat`(以服务端配置为准,见 `src/config/config.js`)
|
||||
- Topic:默认 `blwlog4Nodejs-rcu-heartbeat-topic`(以服务端配置为准,见 `src/config/config.js`)
|
||||
- 编码:UTF-8
|
||||
- 建议消息格式:JSON(便于跨语言对接与灰度演进)
|
||||
|
||||
> 注意:当前服务端代码的“二进制解包”尚未实现,若你们已经有既定二进制协议,需要在 Processor 中落地对应解包逻辑,并在本文档补充协议细节。
|
||||
> 服务端会以 buffer 方式接收 Kafka message.value,并按 UTF-8 解码为 JSON。
|
||||
|
||||
## 2. 消息 Key(强烈建议)
|
||||
为了保证同设备消息更有序、便于消费端批量聚合:
|
||||
@@ -23,7 +23,7 @@
|
||||
| hotel_id | number/int | 12 | 酒店编号(int2 范围内) |
|
||||
| room_id | number/int | 1203 | 房间编号/房间标识(int4) |
|
||||
| device_id | string | "A1B2C3D4" | 设备唯一 ID(序列号/MAC/自定义编码) |
|
||||
| ip | string | "192.168.1.10" | IPv4/IPv6 字符串(落库为 inet) |
|
||||
| ip | string | "192.168.1.10:8080" | `IP:PORT` 字符串(落库为 varchar(21)) |
|
||||
| power_state | number/int | 1 | 取电状态(枚举值需统一标准) |
|
||||
| guest_type | number/int | 0 | 住客身份(住客/空房/保洁/维修等,枚举值需统一标准) |
|
||||
| cardless_state | number/int | 0 | 无卡取电/无卡策略状态(枚举) |
|
||||
@@ -61,6 +61,13 @@
|
||||
"meter": {"p": 123.4, "e_wh": 5678}
|
||||
}
|
||||
}
|
||||
|
||||
## 4.1 C# 生产者示例(与你们当前实现一致)
|
||||
```csharp
|
||||
var nas = JsonConvert.SerializeObject(s);
|
||||
var data = Encoding.UTF8.GetBytes(nas);
|
||||
// 将 data 作为 Kafka message.value 发送即可
|
||||
```
|
||||
```
|
||||
|
||||
## 5. 推送方式(实现建议)
|
||||
|
||||
136
docs/redis-integration-protocol.md
Normal file
136
docs/redis-integration-protocol.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# Redis 对接协议(供 AI 生成代码使用)
|
||||
|
||||
本文档定义“外部项目 ↔ BLS Project Console”之间通过 Redis 交互的 **Key 命名、数据类型、写入方式、读取方式与数据格式**。
|
||||
|
||||
> 约束:每个需要关联本控制台的外部项目,必须在本项目使用的同一个 Redis 实例中:
|
||||
>
|
||||
> - 写入 2 个 Key(心跳 + 控制台信息)
|
||||
> - 命令下发为 HTTP API 调用
|
||||
|
||||
## 1. 命名约定
|
||||
|
||||
令:
|
||||
|
||||
- `projectName`:外部项目名称(建议只用字母数字下划线 `A-Za-z0-9_`;如使用中文也可,但需保证统一且 UTF-8)。
|
||||
|
||||
固定后缀:
|
||||
|
||||
- 心跳:`${projectName}_项目心跳`
|
||||
- 控制台:`${projectName}_项目控制台`
|
||||
|
||||
示例(projectName = `订单系统`):
|
||||
|
||||
- `订单系统_项目心跳`
|
||||
- `订单系统_项目控制台`
|
||||
|
||||
## 2. 外部项目需要写入的 2 个 Key
|
||||
|
||||
### 2.1 `${projectName}_项目心跳`
|
||||
|
||||
- Redis 数据类型:**STRING**
|
||||
- 写入方式:`SET ${projectName}_项目心跳 <json>`
|
||||
- value:JSON 字符串,必须包含目标项目可被调用的 `apiBaseUrl`,以及活跃时间戳 `lastActiveAt`
|
||||
|
||||
推荐 JSON Schema:
|
||||
|
||||
```json
|
||||
{
|
||||
"apiBaseUrl": "http://127.0.0.1:4001",
|
||||
"lastActiveAt": 1760000000000
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
|
||||
- `apiBaseUrl`:目标项目对外提供的 API 地址(基地址,后端将基于它拼接 `apiName`)
|
||||
- `lastActiveAt`:状态时间(活跃时间戳,毫秒)。建议每 **3 秒**刷新一次。
|
||||
|
||||
在线/离线判定(BLS Project Console 使用):
|
||||
|
||||
- 若 `now - lastActiveAt > 10_000ms`,则认为该应用 **离线**
|
||||
- 否则认为 **在线**
|
||||
|
||||
建议:
|
||||
|
||||
- `lastActiveAt` 使用 `Date.now()` 生成(毫秒)
|
||||
- 可设置 TTL(可选):例如 `SET key value EX 30`
|
||||
|
||||
### 2.2 `${projectName}_项目控制台`
|
||||
|
||||
- Redis 数据类型:**LIST**(作为项目向控制台追加的“消息队列/日志队列”)
|
||||
- 写入方式(推荐 FIFO):`RPUSH ${projectName}_项目控制台 <json>`
|
||||
|
||||
value(推荐格式):一条 JSON 字符串,表示“错误/调试信息”或日志记录。
|
||||
|
||||
推荐 JSON Schema(字段尽量保持稳定,便于控制台解析):
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2026-01-12T12:34:56.789Z",
|
||||
"level": "info",
|
||||
"message": "连接成功",
|
||||
"metadata": {
|
||||
"module": "redis",
|
||||
"host": "127.0.0.1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
|
||||
- `timestamp`:ISO-8601 时间字符串
|
||||
- `level`:建议取值 `info|warn|error|debug`(小写)
|
||||
- `message`:日志文本
|
||||
- `metadata`:可选对象(附加信息)
|
||||
|
||||
## 3. 命令下发方式(HTTP API 控制)
|
||||
|
||||
控制台不再通过 Redis 写入控制指令队列;改为由 BLS Project Console 后端根据目标项目心跳里的 `apiBaseUrl` 直接调用目标项目 HTTP API。
|
||||
|
||||
### 3.1 控制台输入格式
|
||||
|
||||
一行文本按空格拆分:
|
||||
|
||||
- 第一个 token:`apiName`(接口名/路径片段)
|
||||
- 剩余 token:参数列表(字符串数组)
|
||||
|
||||
示例:
|
||||
|
||||
- `reload`
|
||||
- `reload force`
|
||||
- `user/refreshCache tenantA`
|
||||
|
||||
### 3.2 目标项目需要提供的 API
|
||||
|
||||
后端默认使用 `POST` 调用:
|
||||
|
||||
- `POST {apiBaseUrl}/{apiName}`
|
||||
|
||||
请求体(JSON)示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"commandId": "cmd-1700000000000-abc123",
|
||||
"timestamp": "2026-01-13T00:00:00.000Z",
|
||||
"source": "BLS Project Console",
|
||||
"apiName": "reload",
|
||||
"args": ["force"],
|
||||
"argsText": "force"
|
||||
}
|
||||
```
|
||||
|
||||
返回建议:
|
||||
|
||||
- 2xx 表示成功
|
||||
- 非 2xx 表示失败(控制台会展示 upstreamStatus 与部分返回内容)
|
||||
|
||||
## 4. 兼容与错误处理建议
|
||||
|
||||
- JSON 解析失败:外部项目应记录错误,并丢弃该条消息(避免死循环阻塞消费)。
|
||||
- 消息过长:建议控制单条消息大小(例如 < 64KB)。
|
||||
- 字符编码:统一 UTF-8。
|
||||
|
||||
## 5. 与本项目代码的对应关系(实现中)
|
||||
|
||||
- 后端通过 `/api/commands`:从 `${targetProjectName}_项目心跳` 读取 `apiBaseUrl` 与 `lastActiveAt`,在线时调用目标项目 API。
|
||||
- 后端通过 `/api/logs`:读取 `${projectName}_项目控制台`;并基于 `${projectName}_项目心跳` 返回在线/离线与 API 地址信息。
|
||||
Reference in New Issue
Block a user