feat: 新增设备 API 拉取采集及配套处理能力
- 接入 NDRServer 告警和流量日志,支持凭据与任务管理 - 支持分页拉取、窗口拆分、调度优先级及 WAL 持久化后推进断点 - 增加迟到告警规则重放,优化多条泛化规则选择和事件时间处理 - 补充回归测试、数据库升级脚本及部署文档
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
# v2 增量升级说明
|
||||
|
||||
## 升级内容
|
||||
|
||||
v2 对应提交 `b61ec2e` 之后的改动,执行前默认现场已经完成 v1。
|
||||
|
||||
这次主要增加:
|
||||
|
||||
- NDRServer API 拉取;
|
||||
- TCP、UDP、API 三种接入方式独立开关;
|
||||
- Kafka 消息中的 `receive_time`、`event_time` 和 `point_time_ns`;
|
||||
- API 拉取任务的窗口拆分和调度优先级;
|
||||
- 迟到告警的规则重放;
|
||||
- 同设备多条泛化规则的选择逻辑;
|
||||
- 独立的 InfluxDB V2 Bucket。
|
||||
|
||||
Kafka 不需要新建 Topic,也不要调整消费组 offset。达梦只需要执行本目录的 API 拉取和迟到重放脚本。
|
||||
|
||||
文中几个常用词:
|
||||
|
||||
| 名称 | 含义 |
|
||||
| --- | --- |
|
||||
| checkpoint | 任务已经成功处理到的时间位置 |
|
||||
| lag | Kafka 中还没有消费的消息数量 |
|
||||
| WAL | `syslog-serve` 写入 Kafka 前保存在本地磁盘的数据 |
|
||||
| Bucket | InfluxDB 中保存一组数据的存储空间 |
|
||||
|
||||
## 先确认从哪里开始
|
||||
|
||||
现场分两种情况:
|
||||
|
||||
1. 已经执行过 `upgrade-doc/v1`:从本文“升级前”开始,只执行 v2。
|
||||
2. 从未执行过 `upgrade-doc/v1`:先完成 v1,再回来执行 v2。
|
||||
|
||||
如果不确定,先让 DBA 执行 v1 的 `database/04-verify.sql`。不要用“再执行一次 v1”来试,因为其中包含建表和初始化数据。
|
||||
|
||||
## 人员分工
|
||||
|
||||
| 人员 | 负责内容 |
|
||||
| --- | --- |
|
||||
| DBA | 数据库备份,执行 `database` 目录中的 SQL |
|
||||
| 运维 | InfluxDB、环境变量、证书、容器和 JAR 升级 |
|
||||
| 开发 | 设备接口适配和上线后的字段核对 |
|
||||
|
||||
## 文件说明
|
||||
|
||||
| 文件 | 用途 |
|
||||
| --- | --- |
|
||||
| `config/接入方式开关说明.md` | TCP、UDP、API 拉取的启停组合、任务开关和生效检查 |
|
||||
| `database/README.md` | 数据库脚本执行顺序、注意事项和成功判断方法 |
|
||||
| `database/01-device-api-pull-precheck.sql` | 检查 API 拉取建表条件 |
|
||||
| `database/02-device-api-pull-upgrade.sql` | 创建凭据、任务、checkpoint、运行记录四张表 |
|
||||
| `database/03-device-api-pull-verify.sql` | 验证 API 拉取表、约束和索引 |
|
||||
| `database/04-fairness-late-replay-precheck.sql` | 检查调度优先级和迟到重放建表条件 |
|
||||
| `database/05-fairness-late-replay-upgrade.sql` | 增加调度优先级和两张重放表 |
|
||||
| `database/06-fairness-late-replay-verify.sql` | 验证调度优先级和重放表 |
|
||||
| `database/80-late-replay-backfill-template.sql` | 可选的历史告警补录模板 |
|
||||
| `database/90-device-api-pull-rollback-audit.sql` | 回滚时只读检查 API 拉取数据 |
|
||||
| `database/91-fairness-late-replay-rollback-audit.sql` | 回滚时只读检查迟到重放数据 |
|
||||
|
||||
`80`、`90`、`91` 不在正常升级流程中执行。
|
||||
|
||||
## 升级前
|
||||
|
||||
1. 备份达梦数据库,保留旧 JAR、配置和镜像。
|
||||
2. 确认 v1 的 `database/04-verify.sql` 已执行成功。
|
||||
3. 记录 Kafka Topic、消费组 offset 和 lag。
|
||||
4. 记录 InfluxDB 的组织、Bucket 和 Token 配置。
|
||||
5. 暂停现有 API 拉取任务。
|
||||
6. 停止 `syslog-serve`,等主消费组 lag 降到 0 后再停止两个消费者。
|
||||
|
||||
不要清空 Kafka,也不要删除历史数据。
|
||||
|
||||
## 执行达梦脚本
|
||||
|
||||
第一次执行前,先阅读 `database/README.md`。其中说明了哪些脚本只读、哪些脚本会修改数据库,以及脚本已经执行过时应如何判断。
|
||||
|
||||
按下面顺序执行:
|
||||
|
||||
```text
|
||||
01-device-api-pull-precheck.sql
|
||||
02-device-api-pull-upgrade.sql
|
||||
03-device-api-pull-verify.sql
|
||||
04-fairness-late-replay-precheck.sql
|
||||
05-fairness-late-replay-upgrade.sql
|
||||
06-fairness-late-replay-verify.sql
|
||||
```
|
||||
|
||||
每个文件单独执行。上一个文件结果正常后,再执行下一个文件。
|
||||
|
||||
检查结果:
|
||||
|
||||
- `01` 最后一组查询应当为空,表示四张 API 表还没有创建;
|
||||
- `03` 第一组查询应返回四张 `DEVICE_COLLECT_API_*` 表;
|
||||
- `04` 前两组查询应当为空,第三组应返回 `ANALYSIS_CHECKPOINT`;
|
||||
- `06` 应返回 `SCHEDULER_PRIORITY`、两张重放表以及对应索引;
|
||||
- 查询结果中的约束应为 `ENABLED`,索引应为 `VALID`。
|
||||
|
||||
脚本中途报错时不要整份重跑,先查询已经创建的对象。
|
||||
|
||||
设备凭据和任务不使用 SQL 插入。服务启动后,通过 `/api/api-pull-credentials` 和 `/api/api-pull-tasks` 创建。示例见 [api/NDRServer任务配置示例.md](./api/NDRServer任务配置示例.md)。
|
||||
|
||||
## InfluxDB
|
||||
|
||||
当前配置使用:
|
||||
|
||||
```text
|
||||
V1 Bucket = yelangbucket
|
||||
V2 Bucket = yelangbucket_v2
|
||||
写入格式 = V2
|
||||
读取模式 = V1_V2
|
||||
```
|
||||
|
||||
如果还没有 V2 Bucket,可以执行:
|
||||
|
||||
```bash
|
||||
export INFLUX_CONTAINER=<InfluxDB容器名>
|
||||
export INFLUX_ORG=<组织名>
|
||||
export V2_BUCKET=yelangbucket_v2
|
||||
export RETENTION=720h
|
||||
export SHARD_GROUP_DURATION=24h
|
||||
|
||||
bash upgrade-doc/v2/influxdb/01-ensure-v2-bucket.sh
|
||||
```
|
||||
|
||||
脚本发现同名 Bucket 时只显示现有配置,不会修改。还要确认应用 Token 对这个 Bucket 有读写权限。
|
||||
|
||||
命令返回 `401 Unauthorized` 表示当前 Influx CLI 配置没有管理权限,需要运维换用管理员配置后再执行。
|
||||
|
||||
## 配置
|
||||
|
||||
三个服务的新增环境变量分别放在 `config/` 下。
|
||||
|
||||
TCP、UDP 和 API 拉取的打开、关闭及验证方法见 [config/接入方式开关说明.md](./config/接入方式开关说明.md)。
|
||||
|
||||
| 配置文件 | 放到哪个服务 |
|
||||
| --- | --- |
|
||||
| `config/syslog-serve.env.example` | `syslog-serve` |
|
||||
| `config/syslog-consumer-rule.env.example` | `syslog-consumer-rule` |
|
||||
| `config/syslog-consumer.env.example` | `syslog-consumer` |
|
||||
|
||||
示例文件不能直接作为正式配置使用。先复制需要的项目,再把尖括号中的内容换成现场值。
|
||||
|
||||
部署时注意:
|
||||
|
||||
- `SYSLOG_SERVER_ENABLED` 同时控制 TCP 和 UDP,当前版本不能分别开关;
|
||||
- `SYSLOG_SERVER_ENABLED` 和 `DEVICE_API_ENABLED` 可以独立设置或同时打开;
|
||||
- API 拉取还需要单独恢复具体任务,打开全局开关不会自动恢复暂停任务;
|
||||
- `DEVICE_API_ALLOWED_HOSTS` 只填写现场设备地址;
|
||||
- AppKey 和 AppSecret 通过管理接口保存,不写进配置文件;
|
||||
- 自签名证书导入 Java truststore;
|
||||
- 证书使用域名时,在 Compose 中配置固定映射。
|
||||
|
||||
Compose 示例:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
syslog-serve:
|
||||
extra_hosts:
|
||||
- "<设备证书域名>:<设备IP>"
|
||||
```
|
||||
|
||||
## 发布顺序
|
||||
|
||||
三个 JAR 一起升级:
|
||||
|
||||
1. `syslog-consumer`
|
||||
2. `syslog-consumer-rule`
|
||||
3. `syslog-serve`
|
||||
|
||||
先启动 `syslog-consumer`,再启动一台 `syslog-consumer-rule`。确认启动和写库正常后,启动其余实例,最后启动 `syslog-serve`。
|
||||
|
||||
API 任务先执行 validate。先启用告警任务,确认数量、时间和字段正确后,再启用流量日志任务。
|
||||
|
||||
任务创建和启用命令见 [NDRServer任务配置示例](./api/NDRServer任务配置示例.md)。新建任务默认是暂停状态,不会在创建完成后立即拉取。
|
||||
|
||||
## 升级后检查
|
||||
|
||||
- 三个服务启动正常;
|
||||
- Kafka lag 能回到 0,Retry/DLT 没有持续增长;
|
||||
- WAL checkpoint 能追上 durable sequence;
|
||||
- API validate 的配置、DNS、TLS、认证和最小查询全部通过;
|
||||
- API run 中 `recordsFetched` 与 `recordsDurable` 一致,`recordsQuarantined=0`;
|
||||
- 标准化数据按 `event_time` 进入正确日期分区;
|
||||
- 两张迟到重放表没有记录长期停在 `RUNNING`;
|
||||
- InfluxDB V2 Bucket 有新数据。
|
||||
|
||||
## 回滚
|
||||
|
||||
先暂停 API 任务并停止新入口,然后回滚三个 JAR 和配置。
|
||||
|
||||
新增表、字段和索引保留,不删除 API checkpoint、迟到重放记录、Kafka Topic 或消费组 offset。需要核对时执行 `90`、`91` 两个只读脚本。
|
||||
@@ -0,0 +1,154 @@
|
||||
# NDRServer API 拉取配置示例
|
||||
|
||||
以下命令在 `syslog-serve` 启动、v2 数据库脚本验证通过后执行。示例中的地址、设备 ID 和凭据需要替换为现场值。
|
||||
|
||||
先说明两个概念:
|
||||
|
||||
- 凭据:设备提供的 AppKey 和 AppSecret,一台设备的两个任务可以共用一份凭据;
|
||||
- 任务:具体拉取哪一类日志。告警和流量日志是两个任务,各自记录已经拉到的时间。
|
||||
- `configVersion`:任务每修改一次都会增加,用于防止两个人同时覆盖配置。调用修改、暂停或恢复接口时使用查询结果中的最新值。
|
||||
|
||||
## 1. 准备变量
|
||||
|
||||
```bash
|
||||
export SERVE_API=http://127.0.0.1:8189/syslogserve
|
||||
export DEVICE_ID=<设备ID>
|
||||
export NDR_BASE_URL=https://<设备证书域名>/ndr/api
|
||||
export CREDENTIAL_REF=<凭据引用>
|
||||
export APP_KEY=<AppKey>
|
||||
export APP_SECRET=<AppSecret>
|
||||
export INITIAL_START_TIME=<YYYY-MM-DDTHH:mm:ss+08:00>
|
||||
```
|
||||
|
||||
变量说明:
|
||||
|
||||
| 变量 | 填写内容 | 示例格式 |
|
||||
| --- | --- | --- |
|
||||
| `SERVE_API` | `syslog-serve` 管理地址 | `http://127.0.0.1:8189/syslogserve` |
|
||||
| `DEVICE_ID` | 平台中的设备 ID | 整数 |
|
||||
| `NDR_BASE_URL` | NDR 接口根地址,结尾固定为 `/ndr/api` | `https://ndr.example.com/ndr/api` |
|
||||
| `CREDENTIAL_REF` | 本次凭据的名称 | `ndr-prod-01` |
|
||||
| `APP_KEY` | 设备提供的 AppKey | 字符串 |
|
||||
| `APP_SECRET` | 设备提供的 AppSecret | 字符串 |
|
||||
| `INITIAL_START_TIME` | 第一次从什么时间开始拉取 | `2026-09-06T00:00:00+08:00` |
|
||||
|
||||
尖括号表示待填写内容,不能把 `<设备ID>` 这样的文字直接执行。
|
||||
|
||||
凭据通过现场受控终端录入,不提交到代码库。
|
||||
|
||||
## 2. 创建凭据
|
||||
|
||||
```bash
|
||||
curl -fsS -X POST "${SERVE_API}/api/api-pull-credentials" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary "{
|
||||
\"credentialRef\":\"${CREDENTIAL_REF}\",
|
||||
\"deviceId\":${DEVICE_ID},
|
||||
\"adapterType\":\"NDRSERVER_V1\",
|
||||
\"credentialVersion\":\"initial-v1\",
|
||||
\"appKey\":\"${APP_KEY}\",
|
||||
\"appSecret\":\"${APP_SECRET}\"
|
||||
}"
|
||||
```
|
||||
|
||||
接口响应不返回 AppKey、AppSecret 和 Token。
|
||||
|
||||
创建成功时 HTTP 状态码为 `201`,响应中会有 `credentialRef` 和 `configVersion`。返回 `409` 一般表示同名凭据已经存在,此时先查询现有凭据,不要反复创建。
|
||||
|
||||
## 3. 创建告警任务
|
||||
|
||||
```bash
|
||||
curl -fsS -X POST "${SERVE_API}/api/api-pull-tasks" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary "{
|
||||
\"deviceId\":${DEVICE_ID},
|
||||
\"taskName\":\"NDR-威胁告警-API拉取\",
|
||||
\"adapterType\":\"NDRSERVER_V1\",
|
||||
\"streamKey\":\"NDR_ALERT\",
|
||||
\"baseUrl\":\"${NDR_BASE_URL}\",
|
||||
\"credentialRef\":\"${CREDENTIAL_REF}\",
|
||||
\"pollIntervalSeconds\":1,
|
||||
\"pageSize\":100,
|
||||
\"maxPagesPerRun\":1000,
|
||||
\"schedulerPriority\":100,
|
||||
\"connectTimeoutMs\":5000,
|
||||
\"requestTimeoutMs\":30000,
|
||||
\"windowSizeSeconds\":60,
|
||||
\"safetyDelaySeconds\":120,
|
||||
\"lookbackSeconds\":300,
|
||||
\"maxResponseBytes\":16777216,
|
||||
\"initialStartTime\":\"${INITIAL_START_TIME}\",
|
||||
\"extraConfig\":{}
|
||||
}"
|
||||
```
|
||||
|
||||
## 4. 创建流量日志任务
|
||||
|
||||
流量任务和告警任务分别维护 checkpoint:
|
||||
|
||||
```bash
|
||||
curl -fsS -X POST "${SERVE_API}/api/api-pull-tasks" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary "{
|
||||
\"deviceId\":${DEVICE_ID},
|
||||
\"taskName\":\"NDR-原始网络日志-API拉取\",
|
||||
\"adapterType\":\"NDRSERVER_V1\",
|
||||
\"streamKey\":\"NDR_FLOW_LOG\",
|
||||
\"baseUrl\":\"${NDR_BASE_URL}\",
|
||||
\"credentialRef\":\"${CREDENTIAL_REF}\",
|
||||
\"pollIntervalSeconds\":1,
|
||||
\"pageSize\":500,
|
||||
\"maxPagesPerRun\":1000,
|
||||
\"schedulerPriority\":10,
|
||||
\"connectTimeoutMs\":5000,
|
||||
\"requestTimeoutMs\":30000,
|
||||
\"windowSizeSeconds\":60,
|
||||
\"safetyDelaySeconds\":120,
|
||||
\"lookbackSeconds\":0,
|
||||
\"maxResponseBytes\":16777216,
|
||||
\"initialStartTime\":\"${INITIAL_START_TIME}\",
|
||||
\"extraConfig\":{}
|
||||
}"
|
||||
```
|
||||
|
||||
`pageSize=500` 是初始值,上线前根据响应大小、接口耗时和实际吞吐调整。
|
||||
|
||||
## 5. 验证和启用
|
||||
|
||||
任务创建后默认为暂停状态。记录响应中的 `taskId` 和 `configVersion`,执行验证:
|
||||
|
||||
```bash
|
||||
curl -fsS -X POST \
|
||||
"${SERVE_API}/api/api-pull-tasks/<taskId>/validate" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary '{"configVersion":<当前版本>}'
|
||||
```
|
||||
|
||||
验证返回 `valid=true` 后恢复任务:
|
||||
|
||||
```bash
|
||||
curl -fsS -X POST \
|
||||
"${SERVE_API}/api/api-pull-tasks/<taskId>/resume" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary '{"configVersion":<当前版本>}'
|
||||
```
|
||||
|
||||
上线时先启用告警任务,核对数量、事件时间和字段后,再启用流量日志任务。
|
||||
|
||||
常见返回说明:
|
||||
|
||||
| 返回内容 | 处理方式 |
|
||||
| --- | --- |
|
||||
| `valid=false` | 查看 `checks` 中状态为 `FAIL` 的项目,处理后重新验证 |
|
||||
| `CONFIG_VERSION_CONFLICT` | 重新查询任务,使用最新的 `configVersion` |
|
||||
| `enabled=true` | 任务已经开始调度 |
|
||||
| `recordsFetched=recordsDurable` | 本次拉取的数据已经写入 WAL |
|
||||
| `recordsQuarantined>0` | 有数据被隔离,需要查看服务日志 |
|
||||
|
||||
查询任务进度:
|
||||
|
||||
```bash
|
||||
curl -fsS "${SERVE_API}/api/api-pull-tasks/<taskId>/runtime"
|
||||
```
|
||||
|
||||
`committedWindowEnd` 表示已经完整处理到的时间。它持续向后变化,说明任务正在推进。
|
||||
@@ -0,0 +1,19 @@
|
||||
# 新消息写 V2;升级期间同时读取 V1/V2,避免切换窗口丢失旧点。
|
||||
INFLUXDB_RAW_WRITE_SCHEMA=V2
|
||||
INFLUXDB_RAW_READ_MODE=V1_V2
|
||||
INFLUXDB_RAW_V1_BUCKET=yelangbucket
|
||||
INFLUXDB_RAW_V2_BUCKET=yelangbucket_v2
|
||||
INFLUXDB_RAW_UUID_BUCKET_COUNT=4096
|
||||
INFLUXDB_RAW_LEGACY_POINT_TIME_FALLBACK_ENABLED=true
|
||||
INFLUXDB_RAW_QUERY_MAX_ROWS=10000
|
||||
|
||||
# 标准化告警和迟到事实通知在同一个达梦事务中提交。
|
||||
ANALYSIS_LATE_REPLAY_OUTBOX_ENABLED=true
|
||||
|
||||
# 同设备多条泛化规则只选择一个确定性胜出规则。
|
||||
NORMALIZATION_RULE_SELECTION_ENABLED=true
|
||||
NORMALIZATION_RULE_SELECTION_SHADOW_ENABLED=true
|
||||
NORMALIZATION_RULE_SELECTION_AMBIGUOUS_FALLBACK=LOWEST_RULE_ID
|
||||
NORMALIZATION_RULE_SELECTION_DETAIL_LOG_ENABLED=false
|
||||
NORMALIZATION_RULE_SELECTION_EXPLICIT_ENABLED=true
|
||||
NORMALIZATION_RULE_SELECTION_AUTOMATIC_FALLBACK_ENABLED=true
|
||||
@@ -0,0 +1,16 @@
|
||||
# 与 syslog-consumer-rule 使用相同的 V1/V2 Bucket 契约。
|
||||
INFLUXDB_RAW_WRITE_SCHEMA=V2
|
||||
INFLUXDB_RAW_READ_MODE=V1_V2
|
||||
INFLUXDB_RAW_V1_BUCKET=yelangbucket
|
||||
INFLUXDB_RAW_V2_BUCKET=yelangbucket_v2
|
||||
INFLUXDB_RAW_UUID_BUCKET_COUNT=4096
|
||||
INFLUXDB_RAW_LEGACY_POINT_TIME_FALLBACK_ENABLED=true
|
||||
INFLUXDB_RAW_QUERY_MAX_ROWS=10000
|
||||
|
||||
# 独立重放已经完成、但后来到达了告警事实的规则窗口。
|
||||
ANALYSIS_LATE_REPLAY_ENABLED=true
|
||||
ANALYSIS_LATE_REPLAY_SCAN_INTERVAL_MS=5000
|
||||
ANALYSIS_LATE_REPLAY_LEASE_SECONDS=1800
|
||||
ANALYSIS_LATE_REPLAY_MAX_BUCKETS_PER_SCAN=100
|
||||
ANALYSIS_LATE_REPLAY_MAX_WINDOWS_PER_SCAN=10
|
||||
ANALYSIS_LATE_REPLAY_RETRY_DELAY_SECONDS=30
|
||||
@@ -0,0 +1,25 @@
|
||||
# TCP 和 UDP 当前共用一个网络监听开关;API 拉取使用另一个独立开关。
|
||||
# 组合方式和生效步骤见 config/接入方式开关说明.md。
|
||||
# 修改环境变量后需要重新创建容器,仅执行 docker restart 不会加载 Compose 新配置。
|
||||
SYSLOG_SERVER_ENABLED=true
|
||||
DEVICE_API_ENABLED=false
|
||||
|
||||
# 只允许经过批准的设备域名或 IP,多个值使用英文逗号分隔。
|
||||
DEVICE_API_ALLOWED_HOSTS=<ndr.example.com>
|
||||
DEVICE_API_INSTANCE_ID=<当前实例稳定标识>
|
||||
DEVICE_API_SCAN_INTERVAL_MS=5000
|
||||
DEVICE_API_LEASE_SECONDS=120
|
||||
DEVICE_API_GLOBAL_CONCURRENCY=4
|
||||
DEVICE_API_PER_HOST_CONCURRENCY=1
|
||||
DEVICE_API_MAX_PAGES_PER_SLICE=20
|
||||
DEVICE_API_SLOW_PAGE_THRESHOLD_MS=1000
|
||||
DEVICE_API_BACKPRESSURE_TIMEOUT_MS=120000
|
||||
|
||||
# 已完成并投递成功的 WAL 分段保留天数;按磁盘容量规划调整。
|
||||
SYSLOG_WAL_RETENTION_DAYS=2
|
||||
SYSLOG_WAL_DISK_HIGH_WATERMARK_PERCENT=90
|
||||
SYSLOG_WAL_MIN_FREE_BYTES=10737418240
|
||||
SYSLOG_POINT_TIME_WRITE_ENABLED=true
|
||||
|
||||
# 自签名设备证书示例。路径必须通过 volume 挂载进入容器。
|
||||
JAVA_OPTS=-Djavax.net.ssl.trustStore=/app/ssl/syslog-serve-cacerts -Djavax.net.ssl.trustStorePassword=<PASSWORD>
|
||||
@@ -0,0 +1,148 @@
|
||||
# TCP、UDP 和 API 拉取开关说明
|
||||
|
||||
接入开关都配置在 `syslog-serve` 服务中。修改开关不会删除任务、凭据、checkpoint 或历史日志。
|
||||
|
||||
## 1. 两个全局开关
|
||||
|
||||
| 环境变量 | 控制内容 | `true` | `false` |
|
||||
| --- | --- | --- | --- |
|
||||
| `SYSLOG_SERVER_ENABLED` | 网络监听 | 同时打开 TCP 和 UDP Syslog 监听 | 同时关闭 TCP 和 UDP Syslog 监听 |
|
||||
| `DEVICE_API_ENABLED` | 设备 API 拉取调度器 | 允许调度已启用的 API 任务 | 停止调度所有 API 拉取任务 |
|
||||
|
||||
当前版本的 TCP 和 UDP 共用 `SYSLOG_SERVER_ENABLED`,不能通过两个独立环境变量分别打开或关闭。
|
||||
|
||||
`SYSLOG_SERVER_ENABLED` 与 `DEVICE_API_ENABLED` 互不排斥,可以同时打开,也可以只打开其中一种。
|
||||
|
||||
## 2. 常用配置组合
|
||||
|
||||
| 使用方式 | `SYSLOG_SERVER_ENABLED` | `DEVICE_API_ENABLED` |
|
||||
| --- | --- | --- |
|
||||
| 只接收 TCP/UDP 推送 | `true` | `false` |
|
||||
| 只使用 API 拉取 | `false` | `true` |
|
||||
| TCP/UDP 和 API 同时使用 | `true` | `true` |
|
||||
| 暂停所有日志接入 | `false` | `false` |
|
||||
|
||||
例如,只使用 API 拉取:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
syslog-serve:
|
||||
environment:
|
||||
- SYSLOG_SERVER_ENABLED=false
|
||||
- DEVICE_API_ENABLED=true
|
||||
```
|
||||
|
||||
例如,同时使用设备推送和 API 拉取:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
syslog-serve:
|
||||
environment:
|
||||
- SYSLOG_SERVER_ENABLED=true
|
||||
- DEVICE_API_ENABLED=true
|
||||
```
|
||||
|
||||
## 3. 修改后如何生效
|
||||
|
||||
环境变量在 `syslog-serve` 启动时读取。修改 Compose 文件后,需要重新创建容器:
|
||||
|
||||
```bash
|
||||
docker compose -f <Compose文件路径> up -d --force-recreate syslog-serve
|
||||
```
|
||||
|
||||
如果 Compose 中的服务名不是 `syslog-serve`,请换成现场实际服务名。
|
||||
|
||||
只执行下面的命令不能加载刚修改的 Compose 环境变量:
|
||||
|
||||
```bash
|
||||
docker restart syslog-serve-dm
|
||||
```
|
||||
|
||||
`docker restart` 只重启原容器,仍会使用创建该容器时保存的旧环境变量。
|
||||
|
||||
## 4. API 拉取有两层开关
|
||||
|
||||
API 拉取必须同时满足:
|
||||
|
||||
1. 全局开关 `DEVICE_API_ENABLED=true`;
|
||||
2. 具体任务的 `enabled=true`。
|
||||
|
||||
因此,把全局开关改成 `true` 不会自动恢复已经暂停的任务。任务仍需通过管理接口恢复。
|
||||
|
||||
查询任务当前版本:
|
||||
|
||||
```bash
|
||||
export SYSLOG_SERVE_BASE_URL=http://127.0.0.1:8189/syslogserve
|
||||
|
||||
curl -sS \
|
||||
"${SYSLOG_SERVE_BASE_URL}/api/api-pull-tasks/<taskId>"
|
||||
```
|
||||
|
||||
响应中的 `configVersion` 是任务当前版本。恢复任务:
|
||||
|
||||
```bash
|
||||
curl -sS -X POST \
|
||||
"${SYSLOG_SERVE_BASE_URL}/api/api-pull-tasks/<taskId>/resume" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary '{"configVersion":<当前版本>}'
|
||||
```
|
||||
|
||||
暂停任务:
|
||||
|
||||
```bash
|
||||
curl -sS -X POST \
|
||||
"${SYSLOG_SERVE_BASE_URL}/api/api-pull-tasks/<taskId>/pause" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary '{"configVersion":<当前版本>}'
|
||||
```
|
||||
|
||||
每次恢复或暂停成功后,`configVersion` 都会增加。再次操作前要重新查询任务,不能一直使用旧版本号。
|
||||
|
||||
## 5. 检查配置是否生效
|
||||
|
||||
先查看容器实际使用的环境变量:
|
||||
|
||||
```bash
|
||||
docker inspect syslog-serve-dm \
|
||||
--format '{{range .Config.Env}}{{println .}}{{end}}' \
|
||||
| grep -E '^(SYSLOG_SERVER_ENABLED|DEVICE_API_ENABLED)='
|
||||
```
|
||||
|
||||
再查看启动日志:
|
||||
|
||||
```bash
|
||||
docker logs --since 5m syslog-serve-dm 2>&1 \
|
||||
| grep -E 'TCP Syslog server started|UDP Syslog server started|Both TCP and UDP|设备 API 拉取调度器配置'
|
||||
```
|
||||
|
||||
判断方法:
|
||||
|
||||
- 出现 `TCP Syslog server started` 和 `UDP Syslog server started`,表示网络监听已打开;
|
||||
- 没有 TCP/UDP 启动记录,并且容器环境中 `SYSLOG_SERVER_ENABLED=false`,表示网络监听已关闭;
|
||||
- 出现 `设备 API 拉取调度器配置: enabled=true`,表示 API 全局开关已打开;
|
||||
- 出现 `设备 API 拉取调度器配置: enabled=false`,表示 API 全局开关已关闭。
|
||||
|
||||
最后还要查询具体 API 任务:
|
||||
|
||||
```bash
|
||||
curl -sS \
|
||||
"${SYSLOG_SERVE_BASE_URL}/api/api-pull-tasks/<taskId>/runtime"
|
||||
```
|
||||
|
||||
响应中的 `enabled=true` 表示该任务已启用;`committedWindowEnd` 持续向后变化,才表示任务正在正常推进。
|
||||
|
||||
## 6. 端口配置注意事项
|
||||
|
||||
当 `SYSLOG_SERVER_ENABLED=true` 时,Compose 还需要发布 TCP 和 UDP 端口,例如:
|
||||
|
||||
```yaml
|
||||
ports:
|
||||
- "514:514/tcp"
|
||||
- "514:514/udp"
|
||||
```
|
||||
|
||||
端口映射和程序开关是两件事:
|
||||
|
||||
- 只有端口映射、但 `SYSLOG_SERVER_ENABLED=false`,程序不会监听 TCP/UDP;
|
||||
- `SYSLOG_SERVER_ENABLED=true`、但没有正确映射或开放端口,容器外设备仍无法连接;
|
||||
- 只使用 API 拉取时,可以保留端口映射,但建议同时从 Compose 和防火墙中关闭不需要的入口。
|
||||
@@ -0,0 +1,35 @@
|
||||
-- =============================================================================
|
||||
-- 脚本:01-device-api-pull-precheck.sql
|
||||
-- 用途:安装设备 API 拉取基础表之前,检查现有表结构是否满足升级条件。
|
||||
-- 性质:只读脚本,不会修改表结构和业务数据,可以重复执行。
|
||||
-- 执行时机:执行 02-device-api-pull-upgrade.sql 之前。
|
||||
--
|
||||
-- 重点检查:
|
||||
-- 1. device_collect_task.method 当前使用了哪些值,避免新增 API 类型与旧值冲突;
|
||||
-- 2. device_collect_task.id 和 device_device.id 是否都有主键;
|
||||
-- 3. 两个主键字段的数据类型是否分别为 INTEGER/INT 和 BIGINT;
|
||||
-- 4. 四张 DEVICE_COLLECT_API_* 表是否已经存在。
|
||||
--
|
||||
-- 判断方法:
|
||||
-- - 任一 SQL 报错时,不要执行 02,先确认当前用户和 Schema 是否正确;
|
||||
-- - 第四组查询返回 0 行,表示四张 API 拉取表尚未创建;
|
||||
-- - 第四组查询有返回,表示可能执行过升级,应先运行 03 验证,不要直接重跑 02。
|
||||
-- =============================================================================
|
||||
|
||||
-- 第 1 组:查看采集任务 method 的现有取值及任务数量。
|
||||
SELECT method, COUNT(*) AS task_count FROM device_collect_task GROUP BY method ORDER BY method;
|
||||
|
||||
-- 第 2 组:确认两张被引用的旧表都有主键,每张表应各返回一条统计记录。
|
||||
SELECT table_name, COUNT(*) AS pk_count FROM user_constraints
|
||||
WHERE LOWER(table_name) IN ('device_collect_task','device_device') AND constraint_type='P'
|
||||
GROUP BY table_name ORDER BY table_name;
|
||||
|
||||
-- 第 3 组:核对外键关联字段的数据类型、长度和是否允许为空。
|
||||
SELECT table_name,column_name,data_type,data_length,data_precision,data_scale,nullable
|
||||
FROM user_tab_columns
|
||||
WHERE LOWER(table_name) IN ('device_collect_task','device_device') AND LOWER(column_name)='id'
|
||||
ORDER BY table_name;
|
||||
|
||||
-- 第 4 组:检查目标表是否已存在。首次升级时应返回 0 行。
|
||||
SELECT table_name FROM user_tables WHERE LOWER(table_name) IN
|
||||
('device_collect_api_credential','device_collect_api_config','device_collect_api_checkpoint','device_collect_api_run');
|
||||
@@ -0,0 +1,159 @@
|
||||
-- =============================================================================
|
||||
-- 脚本:02-device-api-pull-upgrade.sql
|
||||
-- 用途:创建设备 API 拉取需要的四张基础表、约束和索引。
|
||||
-- 性质:数据库结构变更脚本,会创建对象,不是只读脚本。
|
||||
-- 执行时机:01 预检通过后,部署新版 syslog-serve 之前。
|
||||
--
|
||||
-- 前置条件:
|
||||
-- 1. 已完成数据库备份;
|
||||
-- 2. API 拉取任务和旧版服务已经停止;
|
||||
-- 3. 已确认 device_collect_task.id 与 device_device.id 的真实类型;
|
||||
-- 4. 四张 DEVICE_COLLECT_API_* 表均不存在。
|
||||
--
|
||||
-- 注意:本脚本不是重复执行脚本。执行成功后不要再次执行。
|
||||
-- 如果中途报错,应保留现场并执行 03 验证实际创建情况,不要直接重跑。
|
||||
-- =============================================================================
|
||||
|
||||
-- 凭据表:保存设备、适配器和 AppKey/AppSecret 的对应关系。
|
||||
-- 第一阶段为明文保存,因此禁止把 app_secret 输出到日志或普通查询结果中。
|
||||
CREATE TABLE device_collect_api_credential (
|
||||
credential_ref VARCHAR2(128) NOT NULL,
|
||||
device_id BIGINT NOT NULL,
|
||||
adapter_type VARCHAR2(64) NOT NULL,
|
||||
credential_version VARCHAR2(64) NOT NULL,
|
||||
app_key VARCHAR2(512) NOT NULL,
|
||||
app_secret VARCHAR2(2048) NOT NULL,
|
||||
config_version BIGINT DEFAULT 1 NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
updated_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
CONSTRAINT pk_dc_api_credential PRIMARY KEY(credential_ref),
|
||||
CONSTRAINT fk_dc_api_credential_device FOREIGN KEY(device_id) REFERENCES device_device(id),
|
||||
CONSTRAINT ck_dc_api_credential_ver CHECK(config_version >= 1),
|
||||
CONSTRAINT uk_dc_api_credential_device UNIQUE(credential_ref, device_id, adapter_type)
|
||||
);
|
||||
|
||||
-- 任务配置表:每个 API 拉取任务一条记录。
|
||||
-- collect_task_id 关联现有 device_collect_task.id;任务默认关闭,验证通过后再开启。
|
||||
CREATE TABLE device_collect_api_config (
|
||||
collect_task_id INTEGER NOT NULL,
|
||||
device_id BIGINT NOT NULL,
|
||||
adapter_type VARCHAR2(64) NOT NULL,
|
||||
adapter_version INTEGER DEFAULT 1 NOT NULL,
|
||||
base_url VARCHAR2(1024) NOT NULL,
|
||||
stream_key VARCHAR2(64) NOT NULL,
|
||||
credential_ref VARCHAR2(128) NOT NULL,
|
||||
enabled SMALLINT DEFAULT 0 NOT NULL,
|
||||
next_run_at TIMESTAMP,
|
||||
poll_interval_seconds INTEGER DEFAULT 10 NOT NULL,
|
||||
page_size INTEGER DEFAULT 100 NOT NULL,
|
||||
max_pages_per_run INTEGER DEFAULT 1000 NOT NULL,
|
||||
connect_timeout_ms INTEGER DEFAULT 5000 NOT NULL,
|
||||
request_timeout_ms INTEGER DEFAULT 30000 NOT NULL,
|
||||
window_size_seconds INTEGER DEFAULT 60 NOT NULL,
|
||||
safety_delay_seconds INTEGER DEFAULT 120 NOT NULL,
|
||||
lookback_seconds INTEGER DEFAULT 300 NOT NULL,
|
||||
max_response_bytes BIGINT DEFAULT 16777216 NOT NULL,
|
||||
initial_start_time TIMESTAMP NOT NULL,
|
||||
extra_config_json CLOB NOT NULL,
|
||||
config_version BIGINT DEFAULT 1 NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
updated_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
CONSTRAINT pk_dc_api_cfg PRIMARY KEY(collect_task_id),
|
||||
CONSTRAINT fk_dc_api_cfg_task FOREIGN KEY(collect_task_id) REFERENCES device_collect_task(id),
|
||||
CONSTRAINT fk_dc_api_cfg_credential FOREIGN KEY(credential_ref,device_id,adapter_type)
|
||||
REFERENCES device_collect_api_credential(credential_ref,device_id,adapter_type),
|
||||
CONSTRAINT uk_dc_api_cfg_stream UNIQUE(device_id,adapter_type,stream_key),
|
||||
CONSTRAINT ck_dc_api_cfg_enabled CHECK(enabled IN (0,1)),
|
||||
CONSTRAINT ck_dc_api_cfg_adapter_ver CHECK(adapter_version>=1),
|
||||
CONSTRAINT ck_dc_api_cfg_poll CHECK(poll_interval_seconds BETWEEN 1 AND 86400),
|
||||
CONSTRAINT ck_dc_api_cfg_page CHECK(page_size BETWEEN 1 AND 10000),
|
||||
CONSTRAINT ck_dc_api_cfg_pages CHECK(max_pages_per_run BETWEEN 1 AND 100000),
|
||||
CONSTRAINT ck_dc_api_cfg_conn_to CHECK(connect_timeout_ms BETWEEN 100 AND 120000),
|
||||
CONSTRAINT ck_dc_api_cfg_req_to CHECK(request_timeout_ms BETWEEN 100 AND 600000),
|
||||
CONSTRAINT ck_dc_api_cfg_window CHECK(window_size_seconds BETWEEN 1 AND 1209600),
|
||||
CONSTRAINT ck_dc_api_cfg_delay CHECK(safety_delay_seconds BETWEEN 0 AND 604800),
|
||||
CONSTRAINT ck_dc_api_cfg_lookback CHECK(lookback_seconds BETWEEN 0 AND 1209600),
|
||||
CONSTRAINT ck_dc_api_cfg_resp CHECK(max_response_bytes BETWEEN 1024 AND 268435456),
|
||||
CONSTRAINT ck_dc_api_cfg_ver CHECK(config_version>=1),
|
||||
CONSTRAINT ck_dc_api_cfg_https CHECK(base_url LIKE 'https://%')
|
||||
);
|
||||
CREATE INDEX idx_dc_api_cfg_due ON device_collect_api_config(enabled,next_run_at,collect_task_id);
|
||||
|
||||
-- 进度表:记录任务已经安全写入 WAL 的时间位置,并保存跨实例租约信息。
|
||||
-- committed_window_end 只有在当前窗口完整处理成功后才向后推进。
|
||||
CREATE TABLE device_collect_api_checkpoint (
|
||||
collect_task_id INTEGER NOT NULL,
|
||||
checkpoint_type VARCHAR2(32) NOT NULL,
|
||||
checkpoint_value CLOB NOT NULL,
|
||||
committed_window_end TIMESTAMP,
|
||||
adapter_type VARCHAR2(64) NOT NULL,
|
||||
adapter_version INTEGER NOT NULL,
|
||||
version BIGINT DEFAULT 1 NOT NULL,
|
||||
lease_owner VARCHAR2(128),
|
||||
lease_expires_at TIMESTAMP,
|
||||
fencing_token BIGINT DEFAULT 0 NOT NULL,
|
||||
last_event_time TIMESTAMP,
|
||||
last_external_event_id VARCHAR2(512),
|
||||
created_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
updated_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
CONSTRAINT pk_dc_api_cp PRIMARY KEY(collect_task_id),
|
||||
CONSTRAINT fk_dc_api_cp_cfg FOREIGN KEY(collect_task_id) REFERENCES device_collect_api_config(collect_task_id),
|
||||
CONSTRAINT ck_dc_api_cp_type CHECK(checkpoint_type IN ('TIME_WINDOW','TIME_ID','OPAQUE_CURSOR','EXTERNAL_ID')),
|
||||
CONSTRAINT ck_dc_api_cp_adapter_ver CHECK(adapter_version>=1),
|
||||
CONSTRAINT ck_dc_api_cp_ver CHECK(version>=1), CONSTRAINT ck_dc_api_cp_fence CHECK(fencing_token>=0),
|
||||
CONSTRAINT ck_dc_api_cp_lease CHECK((lease_owner IS NULL AND lease_expires_at IS NULL)
|
||||
OR (lease_owner IS NOT NULL AND lease_expires_at IS NOT NULL))
|
||||
);
|
||||
CREATE INDEX idx_dc_api_cp_lease ON device_collect_api_checkpoint(lease_expires_at,collect_task_id);
|
||||
|
||||
-- 运行记录表:每次调度、手工执行或验证都会留下运行结果,便于排查进度和错误。
|
||||
-- 本表只保存脱敏错误摘要,不保存完整设备响应和认证信息。
|
||||
CREATE TABLE device_collect_api_run (
|
||||
run_id VARCHAR2(36) NOT NULL,
|
||||
collect_task_id INTEGER NOT NULL,
|
||||
device_id BIGINT NOT NULL,
|
||||
adapter_type VARCHAR2(64) NOT NULL,
|
||||
adapter_version INTEGER NOT NULL,
|
||||
stream_key VARCHAR2(64) NOT NULL,
|
||||
instance_id VARCHAR2(128) NOT NULL,
|
||||
config_version BIGINT NOT NULL,
|
||||
fencing_token BIGINT NOT NULL,
|
||||
trigger_type VARCHAR2(16) NOT NULL,
|
||||
status VARCHAR2(16) NOT NULL,
|
||||
logical_window_start TIMESTAMP,
|
||||
logical_window_end TIMESTAMP,
|
||||
query_start TIMESTAMP,
|
||||
query_end TIMESTAMP,
|
||||
pages_fetched INTEGER DEFAULT 0 NOT NULL,
|
||||
records_fetched BIGINT DEFAULT 0 NOT NULL,
|
||||
records_durable BIGINT DEFAULT 0 NOT NULL,
|
||||
records_quarantined BIGINT DEFAULT 0 NOT NULL,
|
||||
duplicate_candidates BIGINT DEFAULT 0 NOT NULL,
|
||||
last_http_status INTEGER,
|
||||
error_code VARCHAR2(128),
|
||||
error_summary VARCHAR2(2000),
|
||||
scheduled_at TIMESTAMP,
|
||||
started_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
finished_at TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
CONSTRAINT pk_dc_api_run PRIMARY KEY(run_id),
|
||||
CONSTRAINT fk_dc_api_run_cfg FOREIGN KEY(collect_task_id) REFERENCES device_collect_api_config(collect_task_id),
|
||||
CONSTRAINT ck_dc_api_run_trigger CHECK(trigger_type IN ('SCHEDULED','MANUAL','VALIDATE')),
|
||||
CONSTRAINT ck_dc_api_run_status CHECK(status IN ('RUNNING','SUCCESS','FAILED','SKIPPED')),
|
||||
CONSTRAINT ck_dc_api_run_counts CHECK(pages_fetched>=0 AND records_fetched>=0 AND records_durable>=0
|
||||
AND records_quarantined>=0 AND duplicate_candidates>=0),
|
||||
CONSTRAINT ck_dc_api_run_fence CHECK(fencing_token>=0)
|
||||
);
|
||||
CREATE INDEX idx_dc_api_run_task_time ON device_collect_api_run(collect_task_id,started_at);
|
||||
CREATE INDEX idx_dc_api_run_status ON device_collect_api_run(status,started_at);
|
||||
|
||||
-- 数据字典注释:方便 DBA 在数据库管理工具中直接查看各表用途。
|
||||
COMMENT ON TABLE device_collect_api_config IS '设备 API 拉取任务非敏感配置,一任务一条';
|
||||
COMMENT ON TABLE device_collect_api_credential IS '设备 API 厂商凭据;第一阶段 AppKey/AppSecret 明文保存,禁止日志和接口响应回显凭据正文';
|
||||
COMMENT ON COLUMN device_collect_api_credential.credential_ref IS '任务引用的全局唯一凭据名称';
|
||||
COMMENT ON COLUMN device_collect_api_credential.app_secret IS '第一阶段明文 AppSecret,后续迁移为密文字段';
|
||||
COMMENT ON TABLE device_collect_api_checkpoint IS '设备 API 已安全进入 WAL 的业务水位及跨实例租约';
|
||||
COMMENT ON TABLE device_collect_api_run IS '设备 API 每次调度、手工触发或验证的脱敏运行审计';
|
||||
COMMENT ON COLUMN device_collect_api_run.error_summary IS '最长 2000 字符的脱敏摘要,禁止保存原始响应和认证信息';
|
||||
|
||||
-- 创建完成后,请立即执行 03-device-api-pull-verify.sql。
|
||||
@@ -0,0 +1,57 @@
|
||||
-- =============================================================================
|
||||
-- 脚本:03-device-api-pull-verify.sql
|
||||
-- 用途:确认设备 API 拉取基础表升级结果是否完整。
|
||||
-- 性质:只读脚本,不会修改表结构和业务数据,可以重复执行。
|
||||
-- 执行时机:02 执行完成后、启动新版 syslog-serve 之前。
|
||||
--
|
||||
-- 成功标准:
|
||||
-- 1. 第 1 组返回四张表;
|
||||
-- 2. 第 2 组所有约束的 STATUS 都是 ENABLED;
|
||||
-- 3. 第 3 组所有索引的 STATUS 都是 VALID;
|
||||
-- 4. 第 4 组能列出四张表的完整字段。
|
||||
-- 任一对象缺失或状态异常时,不要启动 API 拉取任务。
|
||||
-- =============================================================================
|
||||
|
||||
-- 第 1 组:确认四张基础表都已创建。
|
||||
SELECT table_name
|
||||
FROM user_tables
|
||||
WHERE table_name IN (
|
||||
'DEVICE_COLLECT_API_CREDENTIAL',
|
||||
'DEVICE_COLLECT_API_CONFIG',
|
||||
'DEVICE_COLLECT_API_CHECKPOINT',
|
||||
'DEVICE_COLLECT_API_RUN'
|
||||
)
|
||||
ORDER BY table_name;
|
||||
|
||||
-- 第 2 组:确认主键、外键、唯一约束和检查约束均已启用。
|
||||
SELECT table_name, constraint_name, constraint_type, status
|
||||
FROM user_constraints
|
||||
WHERE table_name IN (
|
||||
'DEVICE_COLLECT_API_CREDENTIAL',
|
||||
'DEVICE_COLLECT_API_CONFIG',
|
||||
'DEVICE_COLLECT_API_CHECKPOINT',
|
||||
'DEVICE_COLLECT_API_RUN'
|
||||
)
|
||||
ORDER BY table_name, constraint_name;
|
||||
|
||||
-- 第 3 组:确认四张表相关索引均有效。
|
||||
SELECT table_name, index_name, uniqueness, status
|
||||
FROM user_indexes
|
||||
WHERE table_name IN (
|
||||
'DEVICE_COLLECT_API_CREDENTIAL',
|
||||
'DEVICE_COLLECT_API_CONFIG',
|
||||
'DEVICE_COLLECT_API_CHECKPOINT',
|
||||
'DEVICE_COLLECT_API_RUN'
|
||||
)
|
||||
ORDER BY table_name, index_name;
|
||||
|
||||
-- 第 4 组:核对字段名称、类型、长度和是否允许为空。
|
||||
SELECT table_name, column_name, data_type, data_length, nullable
|
||||
FROM user_tab_columns
|
||||
WHERE table_name IN (
|
||||
'DEVICE_COLLECT_API_CREDENTIAL',
|
||||
'DEVICE_COLLECT_API_CONFIG',
|
||||
'DEVICE_COLLECT_API_CHECKPOINT',
|
||||
'DEVICE_COLLECT_API_RUN'
|
||||
)
|
||||
ORDER BY table_name, column_id;
|
||||
@@ -0,0 +1,46 @@
|
||||
-- =============================================================================
|
||||
-- 脚本:04-fairness-late-replay-precheck.sql
|
||||
-- 用途:升级公平调度和迟到告警重放功能之前,检查当前数据库结构。
|
||||
-- 性质:只读脚本,不会修改表结构和业务数据,可以重复执行。
|
||||
-- 执行时机:执行 05-fairness-late-replay-upgrade.sql 之前。
|
||||
--
|
||||
-- 首次升级的预期结果:
|
||||
-- 1. 第 1 组返回 0 行,表示 SCHEDULER_PRIORITY 尚未添加;
|
||||
-- 2. 第 2 组返回 0 行,表示两张重放表尚未创建;
|
||||
-- 3. 第 3 组返回 ANALYSIS_CHECKPOINT,表示规则分析基础表存在;
|
||||
-- 4. 第 4 组应返回 DEVICE_ID、LOG_TIME、CREATED_AT 三个字段;
|
||||
-- 5. 第 5 组应能看到 NDR_ALERT 和 NDR_FLOW_LOG 任务。
|
||||
--
|
||||
-- 如果第 1 组或第 2 组已经有结果,说明可能升级过,不要直接重跑 05,
|
||||
-- 应先执行 06-fairness-late-replay-verify.sql 判断结构是否完整。
|
||||
-- =============================================================================
|
||||
|
||||
-- 第 1 组:检查任务配置表是否已经有调度优先级字段。
|
||||
SELECT column_name
|
||||
FROM user_tab_columns
|
||||
WHERE table_name='DEVICE_COLLECT_API_CONFIG'
|
||||
AND column_name='SCHEDULER_PRIORITY';
|
||||
|
||||
-- 第 2 组:检查迟到告警和规则重放表是否已经存在。
|
||||
SELECT table_name
|
||||
FROM user_tables
|
||||
WHERE table_name IN ('ANALYSIS_LATE_ALARM_BUCKET','ANALYSIS_RULE_REPLAY_WINDOW')
|
||||
ORDER BY table_name;
|
||||
|
||||
-- 第 3 组:确认现有规则分析进度表存在,应返回一行 ANALYSIS_CHECKPOINT。
|
||||
SELECT table_name
|
||||
FROM user_tables
|
||||
WHERE table_name='ANALYSIS_CHECKPOINT';
|
||||
|
||||
-- 第 4 组:确认标准化告警表具备判断迟到数据所需的字段。
|
||||
SELECT column_name,data_type,nullable
|
||||
FROM user_tab_columns
|
||||
WHERE table_name='SYSLOG_NORMAL_ALARM'
|
||||
AND column_name IN ('DEVICE_ID','LOG_TIME','CREATED_AT')
|
||||
ORDER BY column_name;
|
||||
|
||||
-- 第 5 组:查看现有 API 拉取任务类型及数量,为升级后的优先级赋值做准备。
|
||||
SELECT stream_key,COUNT(*) AS task_count
|
||||
FROM device_collect_api_config
|
||||
GROUP BY stream_key
|
||||
ORDER BY stream_key;
|
||||
@@ -0,0 +1,142 @@
|
||||
-- =============================================================================
|
||||
-- 脚本:05-fairness-late-replay-upgrade.sql
|
||||
-- 用途:增加 API 任务调度优先级,并创建迟到告警规则重放所需的两张表。
|
||||
-- 性质:增量数据库结构变更脚本,会修改表结构和数据。
|
||||
-- 执行时机:04 预检通过后,部署三个新版服务之前。
|
||||
--
|
||||
-- 前置条件:
|
||||
-- 1. 已完成数据库备份;
|
||||
-- 2. API 拉取任务已经暂停;
|
||||
-- 3. syslog-serve、syslog-consumer、syslog-consumer-rule 旧版本已停止;
|
||||
-- 4. SCHEDULER_PRIORITY 字段和两张 ANALYSIS_* 表尚不存在。
|
||||
--
|
||||
-- 注意:本脚本不是重复执行脚本。执行成功后不要再次执行。
|
||||
-- 如果中途报错,应先执行 06 验证已经创建的对象,再决定如何处理。
|
||||
-- =============================================================================
|
||||
|
||||
-- 第 1 步:增加任务调度优先级。
|
||||
-- 数值越大,在到期时间相同的情况下越先执行;默认值 0 兼容旧任务。
|
||||
ALTER TABLE device_collect_api_config
|
||||
ADD scheduler_priority INTEGER DEFAULT 0 NOT NULL;
|
||||
|
||||
ALTER TABLE device_collect_api_config
|
||||
ADD CONSTRAINT ck_dc_api_cfg_priority
|
||||
CHECK(scheduler_priority BETWEEN -1000 AND 1000);
|
||||
|
||||
CREATE INDEX idx_dc_api_cfg_priority_due
|
||||
ON device_collect_api_config(enabled,next_run_at,scheduler_priority,collect_task_id);
|
||||
|
||||
-- 第 2 步:设置现有 NDR 任务的默认优先级。
|
||||
-- 同一 NDR 主机只有一个并发许可时,让低流量告警优先于高流量原始网络日志。
|
||||
UPDATE device_collect_api_config
|
||||
SET scheduler_priority=100,updated_at=SYSDATE
|
||||
WHERE stream_key='NDR_ALERT';
|
||||
|
||||
UPDATE device_collect_api_config
|
||||
SET scheduler_priority=10,updated_at=SYSDATE
|
||||
WHERE stream_key='NDR_FLOW_LOG';
|
||||
|
||||
-- 第 3 步:创建迟到告警分钟桶表。
|
||||
-- 标准化告警入库时,如果其事件分钟已经被实时分析处理过,就在此表登记补处理请求。
|
||||
CREATE TABLE analysis_late_alarm_bucket (
|
||||
id VARCHAR2(36) NOT NULL,
|
||||
device_id BIGINT NOT NULL,
|
||||
bucket_start TIMESTAMP NOT NULL,
|
||||
bucket_end TIMESTAMP NOT NULL,
|
||||
last_observed_at TIMESTAMP NOT NULL,
|
||||
requested_generation BIGINT DEFAULT 1 NOT NULL,
|
||||
claimed_generation BIGINT DEFAULT 0 NOT NULL,
|
||||
processed_generation BIGINT DEFAULT 0 NOT NULL,
|
||||
status VARCHAR2(16) DEFAULT 'PENDING' NOT NULL,
|
||||
attempt_count INTEGER DEFAULT 0 NOT NULL,
|
||||
fencing_token BIGINT DEFAULT 0 NOT NULL,
|
||||
lease_owner VARCHAR2(128),
|
||||
lease_expires_at TIMESTAMP,
|
||||
last_error_code VARCHAR2(128),
|
||||
last_error_summary VARCHAR2(2000),
|
||||
created_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
updated_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
CONSTRAINT pk_analysis_late_alarm_bucket PRIMARY KEY(id),
|
||||
CONSTRAINT uk_analysis_late_alarm_bucket UNIQUE(device_id,bucket_start),
|
||||
CONSTRAINT ck_analysis_late_bucket_status
|
||||
CHECK(status IN ('PENDING','RUNNING','COMPLETED','FAILED')),
|
||||
CONSTRAINT ck_analysis_late_bucket_gen
|
||||
CHECK(requested_generation>=claimed_generation
|
||||
AND claimed_generation>=processed_generation
|
||||
AND processed_generation>=0),
|
||||
CONSTRAINT ck_analysis_late_bucket_count CHECK(attempt_count>=0 AND fencing_token>=0),
|
||||
CONSTRAINT ck_analysis_late_bucket_window CHECK(bucket_end>bucket_start),
|
||||
CONSTRAINT ck_analysis_late_bucket_lease
|
||||
CHECK((lease_owner IS NULL AND lease_expires_at IS NULL)
|
||||
OR (lease_owner IS NOT NULL AND lease_expires_at IS NOT NULL))
|
||||
);
|
||||
|
||||
CREATE INDEX idx_analysis_late_bucket_due
|
||||
ON analysis_late_alarm_bucket(status,lease_expires_at,bucket_start);
|
||||
|
||||
-- 第 4 步:创建规则重放窗口表。
|
||||
-- 系统根据分钟桶和当时适用的规则生成重放窗口,处理结果与正常实时窗口分开记录。
|
||||
CREATE TABLE analysis_rule_replay_window (
|
||||
id VARCHAR2(36) NOT NULL,
|
||||
source_bucket_id VARCHAR2(36) NOT NULL,
|
||||
rule_id VARCHAR2(128) NOT NULL,
|
||||
rule_version VARCHAR2(64) NOT NULL,
|
||||
window_start TIMESTAMP NOT NULL,
|
||||
window_end TIMESTAMP NOT NULL,
|
||||
requested_generation BIGINT DEFAULT 1 NOT NULL,
|
||||
claimed_generation BIGINT DEFAULT 0 NOT NULL,
|
||||
processed_generation BIGINT DEFAULT 0 NOT NULL,
|
||||
status VARCHAR2(16) DEFAULT 'PENDING' NOT NULL,
|
||||
attempt_count INTEGER DEFAULT 0 NOT NULL,
|
||||
input_count BIGINT DEFAULT 0 NOT NULL,
|
||||
output_count BIGINT DEFAULT 0 NOT NULL,
|
||||
fencing_token BIGINT DEFAULT 0 NOT NULL,
|
||||
lease_owner VARCHAR2(128),
|
||||
lease_expires_at TIMESTAMP,
|
||||
next_retry_at TIMESTAMP,
|
||||
last_error_code VARCHAR2(128),
|
||||
last_error_summary VARCHAR2(2000),
|
||||
started_at TIMESTAMP,
|
||||
finished_at TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
updated_at TIMESTAMP DEFAULT SYSDATE NOT NULL,
|
||||
CONSTRAINT pk_analysis_rule_replay PRIMARY KEY(id),
|
||||
CONSTRAINT fk_analysis_rule_replay_bucket FOREIGN KEY(source_bucket_id)
|
||||
REFERENCES analysis_late_alarm_bucket(id),
|
||||
CONSTRAINT uk_analysis_rule_replay
|
||||
UNIQUE(rule_id,rule_version,window_start,window_end),
|
||||
CONSTRAINT ck_analysis_rule_replay_status
|
||||
CHECK(status IN ('PENDING','RUNNING','COMPLETED','FAILED','BLOCKED')),
|
||||
CONSTRAINT ck_analysis_rule_replay_gen
|
||||
CHECK(requested_generation>=claimed_generation
|
||||
AND claimed_generation>=processed_generation
|
||||
AND processed_generation>=0),
|
||||
CONSTRAINT ck_analysis_rule_replay_count
|
||||
CHECK(attempt_count>=0 AND input_count>=0 AND output_count>=0 AND fencing_token>=0),
|
||||
CONSTRAINT ck_analysis_rule_replay_window CHECK(window_end>window_start),
|
||||
CONSTRAINT ck_analysis_rule_replay_lease
|
||||
CHECK((lease_owner IS NULL AND lease_expires_at IS NULL)
|
||||
OR (lease_owner IS NOT NULL AND lease_expires_at IS NOT NULL))
|
||||
);
|
||||
|
||||
CREATE INDEX idx_analysis_rule_replay_due
|
||||
ON analysis_rule_replay_window(status,next_retry_at,lease_expires_at,window_start);
|
||||
|
||||
-- 第 5 步:写入数据字典注释,方便后续运维排查。
|
||||
COMMENT ON COLUMN device_collect_api_config.scheduler_priority
|
||||
IS '到期时间相同时的竞争优先级,数值越大越先调度;逾期更久的任务优先';
|
||||
COMMENT ON TABLE analysis_late_alarm_bucket
|
||||
IS '标准化告警同事务写入的事件分钟 outbox;代数防止运行期间新通知丢失';
|
||||
COMMENT ON COLUMN analysis_late_alarm_bucket.last_observed_at
|
||||
IS '本事件分钟最近一次事务内观察时间,仅供审计,不代表事务提交时间';
|
||||
COMMENT ON TABLE analysis_rule_replay_window
|
||||
IS '迟到告警影响的独立规则重放窗口;不修改正常 RULE checkpoint';
|
||||
COMMENT ON COLUMN analysis_rule_replay_window.rule_version
|
||||
IS '必须与正常 analysis_checkpoint 的规则语义版本完全一致';
|
||||
COMMENT ON COLUMN analysis_rule_replay_window.processed_generation
|
||||
IS '已完整重放的请求代数;小于 requested_generation 时必须再次执行';
|
||||
|
||||
-- 提交本脚本中的优先级更新。
|
||||
COMMIT;
|
||||
|
||||
-- 执行完成后,请立即执行 06-fairness-late-replay-verify.sql。
|
||||
@@ -0,0 +1,61 @@
|
||||
-- =============================================================================
|
||||
-- 脚本:06-fairness-late-replay-verify.sql
|
||||
-- 用途:验证公平调度和迟到告警重放的数据库升级结果。
|
||||
-- 性质:只读脚本,不会修改表结构和业务数据,可以重复执行。
|
||||
-- 执行时机:05 执行完成后、启动三个新版服务之前。
|
||||
--
|
||||
-- 成功标准:
|
||||
-- 1. 第 1 组包含 SCHEDULER_PRIORITY 字段和两张 ANALYSIS_* 表的字段;
|
||||
-- 2. 第 2 组所有约束的 STATUS 都是 ENABLED;
|
||||
-- 3. 第 3 组返回三个索引,STATUS 都是 VALID;
|
||||
-- 4. 第 4 组中 NDR_ALERT 优先级为 100,NDR_FLOW_LOG 优先级为 10;
|
||||
-- 5. 首次升级时,第 5、6 组可以返回 0 行,因为还没有产生迟到数据和重放任务。
|
||||
-- =============================================================================
|
||||
|
||||
-- 第 1 组:检查新增字段和两张新表的字段结构。
|
||||
SELECT table_name,column_name,data_type,nullable,data_default
|
||||
FROM user_tab_columns
|
||||
WHERE (table_name='DEVICE_COLLECT_API_CONFIG' AND column_name='SCHEDULER_PRIORITY')
|
||||
OR table_name IN ('ANALYSIS_LATE_ALARM_BUCKET','ANALYSIS_RULE_REPLAY_WINDOW')
|
||||
ORDER BY table_name,column_id;
|
||||
|
||||
-- 第 2 组:检查新增检查约束、主键、外键和唯一约束是否启用。
|
||||
SELECT table_name,constraint_name,constraint_type,status
|
||||
FROM user_constraints
|
||||
WHERE table_name IN (
|
||||
'DEVICE_COLLECT_API_CONFIG',
|
||||
'ANALYSIS_LATE_ALARM_BUCKET',
|
||||
'ANALYSIS_RULE_REPLAY_WINDOW'
|
||||
)
|
||||
AND (table_name<>'DEVICE_COLLECT_API_CONFIG'
|
||||
OR constraint_name='CK_DC_API_CFG_PRIORITY')
|
||||
ORDER BY table_name,constraint_name;
|
||||
|
||||
-- 第 3 组:检查三个新增索引是否有效。
|
||||
SELECT table_name,index_name,uniqueness,status
|
||||
FROM user_indexes
|
||||
WHERE index_name IN (
|
||||
'IDX_DC_API_CFG_PRIORITY_DUE',
|
||||
'IDX_ANALYSIS_LATE_BUCKET_DUE',
|
||||
'IDX_ANALYSIS_RULE_REPLAY_DUE'
|
||||
)
|
||||
ORDER BY index_name;
|
||||
|
||||
-- 第 4 组:核对现有 API 拉取任务的调度优先级和启停状态。
|
||||
SELECT collect_task_id,stream_key,scheduler_priority,enabled,next_run_at
|
||||
FROM device_collect_api_config
|
||||
ORDER BY scheduler_priority DESC,collect_task_id;
|
||||
|
||||
-- 第 5 组:按状态统计迟到告警分钟桶。刚升级完成时返回 0 行属于正常情况。
|
||||
SELECT status,COUNT(*) AS bucket_count
|
||||
FROM analysis_late_alarm_bucket
|
||||
GROUP BY status
|
||||
ORDER BY status;
|
||||
|
||||
-- 第 6 组:按状态统计规则重放窗口及输入、输出数量。
|
||||
-- 刚升级完成时返回 0 行属于正常情况;运行后可据此观察积压和处理结果。
|
||||
SELECT status,COUNT(*) AS replay_count,
|
||||
SUM(input_count) AS input_count,SUM(output_count) AS output_count
|
||||
FROM analysis_rule_replay_window
|
||||
GROUP BY status
|
||||
ORDER BY status;
|
||||
@@ -0,0 +1,61 @@
|
||||
-- =============================================================================
|
||||
-- 脚本:80-late-replay-backfill-template.sql
|
||||
-- 用途:为升级前已经进入 SYSLOG_NORMAL_ALARM、但错过实时规则窗口的历史告警,
|
||||
-- 补建迟到告警分钟桶,之后由新版规则服务进行重放。
|
||||
-- 性质:可选的数据修复模板,会写入或更新 ANALYSIS_LATE_ALARM_BUCKET。
|
||||
-- 执行时机:05、06 已成功执行且确实需要补处理历史告警时。
|
||||
--
|
||||
-- 重要:本文件包含占位符,不得原样执行。
|
||||
-- 执行前必须完成:
|
||||
-- 1. 将 DEVICE_ID 替换为一个明确的数字,例如 126;
|
||||
-- 2. 将 START_TIME、END_TIME 替换为明确时间,采用左闭右开范围;
|
||||
-- 3. 先执行下面 USING 括号中的 SELECT,核对设备、时间和分钟数量;
|
||||
-- 4. 一次最多按一小时处理,大范围应分成多个小时依次执行;
|
||||
-- 5. 确认没有选中其他设备的数据。
|
||||
--
|
||||
-- 示例范围:
|
||||
-- log_time >= TIMESTAMP '2026-09-06 00:00:00'
|
||||
-- log_time < TIMESTAMP '2026-09-06 01:00:00'
|
||||
-- 表示只处理 00:00:00(含)到 01:00:00(不含)的数据。
|
||||
--
|
||||
-- 成功后,受影响分钟在 ANALYSIS_LATE_ALARM_BUCKET 中为 PENDING,或在原任务
|
||||
-- 正在运行时保持 RUNNING 并增加 requested_generation。随后由规则服务处理。
|
||||
-- =============================================================================
|
||||
|
||||
-- 按“设备 + 事件分钟”合并:已有分钟增加请求代数,新分钟插入一条待处理记录。
|
||||
MERGE INTO analysis_late_alarm_bucket t
|
||||
USING (
|
||||
SELECT
|
||||
device_id,
|
||||
TO_TIMESTAMP(
|
||||
TO_CHAR(log_time,'YYYY-MM-DD HH24:MI') || ':00',
|
||||
'YYYY-MM-DD HH24:MI:SS'
|
||||
) AS bucket_start
|
||||
FROM syslog_normal_alarm
|
||||
WHERE device_id = DEVICE_ID
|
||||
AND log_time >= TIMESTAMP 'START_TIME'
|
||||
AND log_time < TIMESTAMP 'END_TIME'
|
||||
GROUP BY
|
||||
device_id,
|
||||
TO_TIMESTAMP(
|
||||
TO_CHAR(log_time,'YYYY-MM-DD HH24:MI') || ':00',
|
||||
'YYYY-MM-DD HH24:MI:SS'
|
||||
)
|
||||
) s
|
||||
ON (t.device_id=s.device_id AND t.bucket_start=s.bucket_start)
|
||||
WHEN MATCHED THEN UPDATE SET
|
||||
t.requested_generation=t.requested_generation+1,
|
||||
t.last_observed_at=SYSDATE,
|
||||
t.status=CASE WHEN t.status='RUNNING' THEN 'RUNNING' ELSE 'PENDING' END,
|
||||
t.updated_at=SYSDATE
|
||||
WHEN NOT MATCHED THEN INSERT (
|
||||
id,device_id,bucket_start,bucket_end,last_observed_at,
|
||||
requested_generation,claimed_generation,processed_generation,
|
||||
status,attempt_count,fencing_token,created_at,updated_at
|
||||
) VALUES (
|
||||
SYS_GUID(),s.device_id,s.bucket_start,s.bucket_start+(1.0/1440),SYSDATE,
|
||||
1,0,0,'PENDING',0,0,SYSDATE,SYSDATE
|
||||
);
|
||||
|
||||
-- 提交本次历史补数。
|
||||
COMMIT;
|
||||
@@ -0,0 +1,29 @@
|
||||
-- =============================================================================
|
||||
-- 脚本:90-device-api-pull-rollback-audit.sql
|
||||
-- 用途:应用版本回退前,统计设备 API 拉取表中的数据和任务启停状态。
|
||||
-- 性质:只读核验脚本,不会删除表或数据,可以重复执行。
|
||||
--
|
||||
-- 回退原则:
|
||||
-- 1. 关闭全局 DEVICE_API_ENABLED,并暂停所有 API 拉取任务;
|
||||
-- 2. 保留凭据、任务配置、checkpoint 和运行记录,便于恢复和审计;
|
||||
-- 3. 不要为了回退旧应用而删除四张 DEVICE_COLLECT_API_* 表。
|
||||
-- =============================================================================
|
||||
|
||||
-- 第 1 组:统计四张 API 拉取表的记录数量,确认现有数据规模。
|
||||
SELECT 'DEVICE_COLLECT_API_CREDENTIAL' AS table_name, COUNT(*) AS row_count
|
||||
FROM device_collect_api_credential
|
||||
UNION ALL
|
||||
SELECT 'DEVICE_COLLECT_API_CONFIG', COUNT(*)
|
||||
FROM device_collect_api_config
|
||||
UNION ALL
|
||||
SELECT 'DEVICE_COLLECT_API_CHECKPOINT', COUNT(*)
|
||||
FROM device_collect_api_checkpoint
|
||||
UNION ALL
|
||||
SELECT 'DEVICE_COLLECT_API_RUN', COUNT(*)
|
||||
FROM device_collect_api_run;
|
||||
|
||||
-- 第 2 组:统计启用和停用的任务数量。回退前 enabled=1 应为 0 条。
|
||||
SELECT enabled, COUNT(*) AS task_count
|
||||
FROM device_collect_api_config
|
||||
GROUP BY enabled
|
||||
ORDER BY enabled;
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
-- =============================================================================
|
||||
-- 脚本:91-fairness-late-replay-rollback-audit.sql
|
||||
-- 用途:应用版本回退前,检查任务优先级、迟到告警分钟桶和规则重放状态。
|
||||
-- 性质:只读核验脚本,不会删除表或数据,可以重复执行。
|
||||
--
|
||||
-- 回退原则:
|
||||
-- 1. 先暂停全部 API 拉取任务,再停止新版服务;
|
||||
-- 2. 保留 SCHEDULER_PRIORITY 字段和两张 ANALYSIS_* 表;
|
||||
-- 3. 不要删除 PENDING、RUNNING 或 FAILED 记录,避免丢失待处理信息和审计记录;
|
||||
-- 4. 旧版应用会忽略新增字段和新增表。
|
||||
-- =============================================================================
|
||||
|
||||
-- 第 1 组:列出 API 拉取任务的启停状态和优先级。回退前 enabled 应全部为 0。
|
||||
SELECT collect_task_id,stream_key,enabled,scheduler_priority
|
||||
FROM device_collect_api_config
|
||||
ORDER BY collect_task_id;
|
||||
|
||||
-- 第 2 组:统计迟到告警分钟桶状态,记录是否还有待处理或正在处理的任务。
|
||||
SELECT status,COUNT(*) AS bucket_count
|
||||
FROM analysis_late_alarm_bucket
|
||||
GROUP BY status
|
||||
ORDER BY status;
|
||||
|
||||
-- 第 3 组:统计规则重放窗口状态,记录是否还有待处理、失败或阻塞的任务。
|
||||
SELECT status,COUNT(*) AS replay_count
|
||||
FROM analysis_rule_replay_window
|
||||
GROUP BY status
|
||||
ORDER BY status;
|
||||
@@ -0,0 +1,82 @@
|
||||
# v2 数据库升级说明
|
||||
|
||||
本目录中的脚本供达梦数据库管理员手工执行。请使用 `syslog-serve` 实际连接的数据库用户执行,不要使用其他业务库或其他 Schema。
|
||||
|
||||
## 1. 脚本分组
|
||||
|
||||
### 第一组:设备 API 拉取基础表
|
||||
|
||||
首次安装设备 API 拉取功能时,依次执行:
|
||||
|
||||
1. `01-device-api-pull-precheck.sql`:检查旧表主键和新表是否已经存在,只读。
|
||||
2. `02-device-api-pull-upgrade.sql`:创建凭据、任务配置、进度和运行记录表,会修改数据库。
|
||||
3. `03-device-api-pull-verify.sql`:检查新表、约束、索引和字段,只读。
|
||||
|
||||
如果四张 `DEVICE_COLLECT_API_*` 表已经存在,不要再次执行 `02`。
|
||||
|
||||
### 第二组:公平调度和迟到告警重放
|
||||
|
||||
升级公平调度及迟到告警处理功能时,依次执行:
|
||||
|
||||
1. `04-fairness-late-replay-precheck.sql`:检查升级前结构,只读。
|
||||
2. `05-fairness-late-replay-upgrade.sql`:增加调度优先级,并创建迟到告警处理表,会修改数据库。
|
||||
3. `06-fairness-late-replay-verify.sql`:检查新增字段、表、约束和索引,只读。
|
||||
|
||||
如果 `SCHEDULER_PRIORITY` 字段和两张 `ANALYSIS_*` 表已经存在,不要再次执行 `05`。
|
||||
|
||||
### 辅助脚本
|
||||
|
||||
| 脚本 | 用途 | 是否修改数据 |
|
||||
| --- | --- | --- |
|
||||
| `80-late-replay-backfill-template.sql` | 为升级前已经入库的历史告警补建重放任务 | 是,必须先替换参数 |
|
||||
| `90-device-api-pull-rollback-audit.sql` | 回退应用前检查 API 拉取数据 | 否 |
|
||||
| `91-fairness-late-replay-rollback-audit.sql` | 回退应用前检查调度和重放状态 | 否 |
|
||||
|
||||
## 2. 执行前准备
|
||||
|
||||
执行修改数据库的脚本前,先完成以下事项:
|
||||
|
||||
1. 确认已经完成数据库备份。
|
||||
2. 确认连接的是正确的测试环境或生产环境。
|
||||
3. 确认当前用户可以创建表、索引、约束以及修改表结构。
|
||||
4. 暂停所有 API 拉取任务,避免升级过程中还有任务写入。
|
||||
5. 停止待升级的旧版本服务,避免新旧程序同时运行。
|
||||
|
||||
可以先执行下面的语句确认当前用户:
|
||||
|
||||
```sql
|
||||
SELECT USER AS current_user;
|
||||
```
|
||||
|
||||
## 3. 如何执行
|
||||
|
||||
可以使用达梦管理工具或现场常用的数据库客户端打开脚本执行。每个脚本应当单独执行,执行完成并核对结果后,再执行下一个脚本。
|
||||
|
||||
不要一次选择整个目录中的全部脚本执行,因为预检、升级、验证和历史补数的用途不同。
|
||||
|
||||
## 4. 如何判断执行成功
|
||||
|
||||
- 预检脚本:SQL 能正常返回,并且结果符合脚本开头写明的预期。
|
||||
- 升级脚本:所有 DDL 和 DML 均执行成功,没有报错。
|
||||
- 验证脚本:新增对象都能查到,约束状态为 `ENABLED`,索引状态为 `VALID`。
|
||||
- 历史补数脚本:必须先查询并确认时间范围,然后才允许执行 `MERGE`。
|
||||
|
||||
如果出现“对象已经存在”“列已经存在”之类的错误,不要继续重复执行升级脚本。先运行对应的验证脚本,判断之前是否已经升级成功。
|
||||
|
||||
## 5. 推荐执行顺序
|
||||
|
||||
全新升级时:
|
||||
|
||||
```text
|
||||
01(检查)→ 02(升级)→ 03(验证)
|
||||
↓
|
||||
04(检查)→ 05(升级)→ 06(验证)
|
||||
```
|
||||
|
||||
已经安装过设备 API 拉取基础表,只升级本次新增功能时:
|
||||
|
||||
```text
|
||||
04(检查)→ 05(升级)→ 06(验证)
|
||||
```
|
||||
|
||||
`80`、`90` 和 `91` 不属于正常安装步骤,没有明确需要时不要执行。
|
||||
@@ -0,0 +1,66 @@
|
||||
# 设备 API 适配器开发说明
|
||||
|
||||
API 拉取代码放在 `syslog-serve`,不单独建 Maven 模块。
|
||||
|
||||
如果只是接入当前 NDRServer,不需要重新写整套拉取程序。先核对现有适配器是否缺少字段或接口参数,有差异时只修改 NDR 适配器。
|
||||
|
||||
## NDRServer
|
||||
|
||||
现有代码:
|
||||
|
||||
```text
|
||||
syslog-serve/src/main/java/com/haobang/apipull/adapter/ndr/NdrServerApiAdapter.java
|
||||
```
|
||||
|
||||
测试代码:
|
||||
|
||||
```text
|
||||
syslog-serve/src/test/java/com/haobang/apipull/adapter/ndr/NdrServerApiAdapterTest.java
|
||||
syslog-serve/src/test/java/com/haobang/apipull/adapter/ndr/NdrServerSpringWiringTest.java
|
||||
```
|
||||
|
||||
现有 NDR 拉取实现如需补充特殊参数或字段处理,直接修改上述适配器和测试。定时任务、线程池、checkpoint 和 Kafka Producer 使用项目公共实现。
|
||||
|
||||
## 新厂商
|
||||
|
||||
新建厂商目录:
|
||||
|
||||
```text
|
||||
syslog-serve/src/main/java/com/haobang/apipull/adapter/<vendor>/
|
||||
```
|
||||
|
||||
实现 `ApiPullAdapter` 并加上 `@Component`。Spring 启动后会自动注册。
|
||||
|
||||
接口方法的作用:
|
||||
|
||||
| 方法 | 要返回什么 |
|
||||
| --- | --- |
|
||||
| `type()` | 厂商和协议版本的固定名称,例如 `VENDOR_X_V1` |
|
||||
| `version()` | 当前代码的协议版本号 |
|
||||
| `streams()` | 支持的日志类型,例如告警、流量日志 |
|
||||
| `minimumWindowSeconds()` | 设备允许查询的最小时间范围 |
|
||||
| `validateConfig()` | 检查地址、分页大小和超时时间 |
|
||||
| `pull()` | 查询指定时间范围中的一页数据 |
|
||||
|
||||
适配器负责以下内容:
|
||||
|
||||
- 认证和 Token;
|
||||
- 请求地址、参数和时间格式;
|
||||
- 单页数据查询;
|
||||
- 响应解析和厂商错误码;
|
||||
- 事件时间、设备侧 ID 和平台事件 ID;
|
||||
- 原始 JSON 及必要的兼容字段。
|
||||
|
||||
调度、并发、窗口拆分、checkpoint、WAL 和 Kafka 由公共代码处理。适配器不要直接写 Kafka,也不要自行推进 checkpoint。
|
||||
|
||||
如果新厂商不是 AppKey/AppSecret 认证,还需要一起调整凭据 DTO、`ApiCredentialService`、`DatabaseCredentialProvider` 和数据库脚本。
|
||||
|
||||
开发完成后至少检查:
|
||||
|
||||
1. 认证成功、认证失败和 Token 过期;
|
||||
2. 接口返回空数据时任务能够正常推进;
|
||||
3. 多页数据没有漏页;
|
||||
4. 事件时间来自设备日志,不使用接口响应时间;
|
||||
5. 同一条设备日志重复拉取时 `eventId` 保持不变;
|
||||
6. 接口异常时 checkpoint 不推进;
|
||||
7. 单元测试和 Spring 启动测试通过。
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
: "${INFLUX_CONTAINER:?请设置 INFLUX_CONTAINER}"
|
||||
: "${INFLUX_ORG:?请设置 INFLUX_ORG}"
|
||||
|
||||
INFLUX_CONFIG_PATH="${INFLUX_CONFIG_PATH:-/etc/influxdb2/influx-configs}"
|
||||
V2_BUCKET="${V2_BUCKET:-yelangbucket_v2}"
|
||||
RETENTION="${RETENTION:-720h}"
|
||||
SHARD_GROUP_DURATION="${SHARD_GROUP_DURATION:-24h}"
|
||||
|
||||
command -v docker >/dev/null 2>&1 || {
|
||||
echo "ERROR: 当前主机没有 docker 命令" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "检查 InfluxDB V2 Bucket: ${V2_BUCKET}"
|
||||
BUCKETS="$(docker exec "${INFLUX_CONTAINER}" influx bucket list \
|
||||
--configs-path "${INFLUX_CONFIG_PATH}")"
|
||||
|
||||
if printf '%s\n' "${BUCKETS}" | awk -v expected="${V2_BUCKET}" '
|
||||
NR > 1 && $2 == expected { found=1 }
|
||||
END { exit(found ? 0 : 1) }
|
||||
'
|
||||
then
|
||||
echo "Bucket 已存在,脚本不会修改:"
|
||||
printf '%s\n' "${BUCKETS}" | awk -v expected="${V2_BUCKET}" \
|
||||
'NR == 1 || $2 == expected'
|
||||
echo "请人工确认 Retention、Shard group duration 和应用 Token 权限。"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "创建 Bucket: name=${V2_BUCKET}, retention=${RETENTION}, shard=${SHARD_GROUP_DURATION}"
|
||||
docker exec "${INFLUX_CONTAINER}" influx bucket create \
|
||||
--configs-path "${INFLUX_CONFIG_PATH}" \
|
||||
--org "${INFLUX_ORG}" \
|
||||
--name "${V2_BUCKET}" \
|
||||
--retention "${RETENTION}" \
|
||||
--shard-group-duration "${SHARD_GROUP_DURATION}"
|
||||
|
||||
echo "创建后核验:"
|
||||
docker exec "${INFLUX_CONTAINER}" influx bucket list \
|
||||
--configs-path "${INFLUX_CONFIG_PATH}" \
|
||||
| awk -v expected="${V2_BUCKET}" 'NR == 1 || $2 == expected'
|
||||
|
||||
echo "PASS: V2 Bucket 已存在;脚本未删除或修改其他 Bucket。"
|
||||
Reference in New Issue
Block a user