docs: clarify kafka-only production channel
This commit is contained in:
11
README.md
11
README.md
@@ -18,7 +18,7 @@
|
|||||||
| 框架 | Spring Boot 3.5.3 |
|
| 框架 | Spring Boot 3.5.3 |
|
||||||
| 网络 | Netty 4.2.9.Final |
|
| 网络 | Netty 4.2.9.Final |
|
||||||
| 并发 | Disruptor 4 + 虚拟线程 + `StructuredTaskScope` |
|
| 并发 | Disruptor 4 + 虚拟线程 + `StructuredTaskScope` |
|
||||||
| 消息队列 | **Kafka**(vin 分区,保证单车有序) |
|
| 事件流 | **Kafka**(唯一生产消息通道,vin 分区,保证单车有序) |
|
||||||
| 线上消息格式 | **Protobuf**,调试走 JSON |
|
| 线上消息格式 | **Protobuf**,调试走 JSON |
|
||||||
| MQTT 客户端 | Eclipse Paho 1.2.5 |
|
| MQTT 客户端 | Eclipse Paho 1.2.5 |
|
||||||
| 会话索引 | Redis |
|
| 会话索引 | Redis |
|
||||||
@@ -96,7 +96,8 @@ Redis 最新状态查询不在默认 Maven reactor 中;需要时使用 `-Popti
|
|||||||
## 核心原则
|
## 核心原则
|
||||||
|
|
||||||
1. **接入与业务落库分离**:协议接入应用只负责收、解析、校验、规整和投递 Kafka;`vehicle-history-app` 写入 TDengine 历史与 RAW JSON,`vehicle-analytics-app` 将 JT808 `daily_mileage_km` 写入 MySQL `vehicle_stat_metric`
|
1. **接入与业务落库分离**:协议接入应用只负责收、解析、校验、规整和投递 Kafka;`vehicle-history-app` 写入 TDengine 历史与 RAW JSON,`vehicle-analytics-app` 将 JT808 `daily_mileage_km` 写入 MySQL `vehicle_stat_metric`
|
||||||
2. **协议即插拔**:每个 `protocol-*` / `inbound-*` 都可独立开关(`lingniu.ingest.<name>.enabled`)
|
2. **Kafka 唯一消息通道**:生产链路不提供 RabbitMQ、RocketMQ 或其他 MQ 后端;接入、历史、统计统一通过 Kafka Envelope 解耦
|
||||||
3. **顺序保证**:同一 VIN 严格有序(Disruptor hash + Kafka 分区 key)
|
3. **协议即插拔**:每个 `protocol-*` / `inbound-*` 都可独立开关(`lingniu.ingest.<name>.enabled`)
|
||||||
4. **幂等消费**:Envelope 带 `eventId`,下游去重
|
4. **顺序保证**:同一 VIN 严格有序(Disruptor hash + Kafka 分区 key)
|
||||||
5. **原始可回放**:协议接入会把 `rawArchiveKey/rawArchiveUri` 追加到事件 metadata;Kafka Envelope、TDengine `raw_frames` 和导出都使用 `archive://...` 逻辑 URI 追溯原始 bytes,实际文件由 `sink-archive` 管理
|
5. **幂等消费**:Envelope 带 `eventId`,下游去重
|
||||||
|
6. **原始可回放**:协议接入会把 `rawArchiveKey/rawArchiveUri` 追加到事件 metadata;Kafka Envelope、TDengine `raw_frames` 和导出都使用 `archive://...` 逻辑 URI 追溯原始 bytes,实际文件由 `sink-archive` 管理
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ java -jar modules/apps/jt808-ingest-app/target/jt808-ingest-app.jar
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -sS http://127.0.0.1:20400/actuator/health
|
curl -sS http://127.0.0.1:20400/actuator/health
|
||||||
|
curl -sS http://127.0.0.1:20400/actuator/health/liveness
|
||||||
|
curl -sS http://127.0.0.1:20400/actuator/health/readiness
|
||||||
lsof -nP -iTCP:808 -sTCP:LISTEN
|
lsof -nP -iTCP:808 -sTCP:LISTEN
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -74,6 +76,8 @@ java -jar modules/apps/gb32960-ingest-app/target/gb32960-ingest-app.jar
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -sS http://127.0.0.1:20100/actuator/health
|
curl -sS http://127.0.0.1:20100/actuator/health
|
||||||
|
curl -sS http://127.0.0.1:20100/actuator/health/liveness
|
||||||
|
curl -sS http://127.0.0.1:20100/actuator/health/readiness
|
||||||
lsof -nP -iTCP:32960 -sTCP:LISTEN
|
lsof -nP -iTCP:32960 -sTCP:LISTEN
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -90,6 +94,8 @@ java -jar modules/apps/vehicle-history-app/target/vehicle-history-app.jar
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -sS http://127.0.0.1:20200/actuator/health
|
curl -sS http://127.0.0.1:20200/actuator/health
|
||||||
|
curl -sS http://127.0.0.1:20200/actuator/health/liveness
|
||||||
|
curl -sS http://127.0.0.1:20200/actuator/health/readiness
|
||||||
curl -sS http://127.0.0.1:20200/v3/api-docs \
|
curl -sS http://127.0.0.1:20200/v3/api-docs \
|
||||||
| grep -E '/api/event-history/locations|/api/event-history/raw-frames'
|
| grep -E '/api/event-history/locations|/api/event-history/raw-frames'
|
||||||
```
|
```
|
||||||
@@ -127,8 +133,14 @@ JT808 注册身份绑定:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -sS http://127.0.0.1:20400/actuator/health
|
curl -sS http://127.0.0.1:20400/actuator/health
|
||||||
|
curl -sS http://127.0.0.1:20400/actuator/health/liveness
|
||||||
|
curl -sS http://127.0.0.1:20400/actuator/health/readiness
|
||||||
curl -sS http://127.0.0.1:20100/actuator/health
|
curl -sS http://127.0.0.1:20100/actuator/health
|
||||||
|
curl -sS http://127.0.0.1:20100/actuator/health/liveness
|
||||||
|
curl -sS http://127.0.0.1:20100/actuator/health/readiness
|
||||||
curl -sS http://127.0.0.1:20200/actuator/health
|
curl -sS http://127.0.0.1:20200/actuator/health
|
||||||
|
curl -sS http://127.0.0.1:20200/actuator/health/liveness
|
||||||
|
curl -sS http://127.0.0.1:20200/actuator/health/readiness
|
||||||
```
|
```
|
||||||
|
|
||||||
Swagger:
|
Swagger:
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ class MavenModuleProfileTest {
|
|||||||
.contains("Netty " + projectProperty(pom, "netty.version"))
|
.contains("Netty " + projectProperty(pom, "netty.version"))
|
||||||
.contains("Eclipse Paho " + projectProperty(pom, "paho-mqtt.version"))
|
.contains("Eclipse Paho " + projectProperty(pom, "paho-mqtt.version"))
|
||||||
.contains("session-core/ 设备会话 + 鉴权 + Token + Redis SessionStore")
|
.contains("session-core/ 设备会话 + 鉴权 + Token + Redis SessionStore")
|
||||||
|
.contains("| 事件流 | **Kafka**(唯一生产消息通道,vin 分区,保证单车有序) |")
|
||||||
.contains("protocol-jt1078/ JT/T 1078(optional-command-gateway profile")
|
.contains("protocol-jt1078/ JT/T 1078(optional-command-gateway profile")
|
||||||
.contains("protocol-jsatl12/ 苏标主动安全报警附件(optional-attachments profile)")
|
.contains("protocol-jsatl12/ 苏标主动安全报警附件(optional-attachments profile)")
|
||||||
.contains("vehicle-state-service/ Kafka 全字段事件消费 + Redis 热状态查询(optional-latest-state profile)")
|
.contains("vehicle-state-service/ Kafka 全字段事件消费 + Redis 热状态查询(optional-latest-state profile)")
|
||||||
@@ -177,6 +178,7 @@ class MavenModuleProfileTest {
|
|||||||
.contains("vehicle-history-app/ TDengine 历史查询 + RAW JSON")
|
.contains("vehicle-history-app/ TDengine 历史查询 + RAW JSON")
|
||||||
.contains("vehicle-analytics-app/ JT808 每日里程指标消费")
|
.contains("vehicle-analytics-app/ JT808 每日里程指标消费")
|
||||||
.contains("协议接入应用只负责收、解析、校验、规整和投递 Kafka")
|
.contains("协议接入应用只负责收、解析、校验、规整和投递 Kafka")
|
||||||
|
.contains("生产链路不提供 RabbitMQ、RocketMQ 或其他 MQ 后端")
|
||||||
.contains("`vehicle-analytics-app` 将 JT808 `daily_mileage_km` 写入 MySQL `vehicle_stat_metric`")
|
.contains("`vehicle-analytics-app` 将 JT808 `daily_mileage_km` 写入 MySQL `vehicle_stat_metric`")
|
||||||
.doesNotContain("Spring Boot 3.4")
|
.doesNotContain("Spring Boot 3.4")
|
||||||
.doesNotContain("Netty 4.1")
|
.doesNotContain("Netty 4.1")
|
||||||
@@ -189,7 +191,8 @@ class MavenModuleProfileTest {
|
|||||||
.doesNotContain("Parquet + DuckDB 文件型明细库")
|
.doesNotContain("Parquet + DuckDB 文件型明细库")
|
||||||
.doesNotContain("车辆状态/日统计消费")
|
.doesNotContain("车辆状态/日统计消费")
|
||||||
.doesNotContain("本服务不写业务库")
|
.doesNotContain("本服务不写业务库")
|
||||||
.doesNotContain("里程统计全部由 Kafka 下游消费者实现");
|
.doesNotContain("里程统计全部由 Kafka 下游消费者实现")
|
||||||
|
.doesNotContain("| 消息队列 |");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -111,6 +111,18 @@ class PortainerComposeResourceLimitsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void tdengineVerificationRunbookChecksLivenessAndReadinessForManagedApps() throws IOException {
|
||||||
|
String runbook = Files.readString(repositoryRoot()
|
||||||
|
.resolve("docs/operations/vehicle-ingest-tdengine-verification.md"));
|
||||||
|
|
||||||
|
for (String httpPort : List.of("20100", "20400", "20200")) {
|
||||||
|
assertThat(runbook)
|
||||||
|
.contains("curl -sS http://127.0.0.1:" + httpPort + "/actuator/health/liveness")
|
||||||
|
.contains("curl -sS http://127.0.0.1:" + httpPort + "/actuator/health/readiness");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void dockerEntrypointExecsJavaForSignalHandling() throws IOException {
|
void dockerEntrypointExecsJavaForSignalHandling() throws IOException {
|
||||||
String dockerfile = Files.readString(repositoryRoot().resolve("Dockerfile"));
|
String dockerfile = Files.readString(repositoryRoot().resolve("Dockerfile"));
|
||||||
|
|||||||
Reference in New Issue
Block a user