chore: align analytics port with ecs runtime
This commit is contained in:
@@ -14,6 +14,6 @@ RUN apt-get update \
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY modules/apps/${APP_NAME}/target/${APP_NAME}.jar /app/app.jar
|
COPY modules/apps/${APP_NAME}/target/${APP_NAME}.jar /app/app.jar
|
||||||
|
|
||||||
EXPOSE 20100 20200 20300 20400 20500 32960 808
|
EXPOSE 20100 20200 20310 20400 20500 32960 808
|
||||||
|
|
||||||
ENTRYPOINT ["sh", "-c", "exec java $JAVA_OPTS -jar /app/app.jar"]
|
ENTRYPOINT ["sh", "-c", "exec java $JAVA_OPTS -jar /app/app.jar"]
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ services:
|
|||||||
mem_limit: ${VEHICLE_ANALYTICS_MEM_LIMIT:-1024m}
|
mem_limit: ${VEHICLE_ANALYTICS_MEM_LIMIT:-1024m}
|
||||||
environment:
|
environment:
|
||||||
<<: *common-env
|
<<: *common-env
|
||||||
HTTP_PORT: 20300
|
HTTP_PORT: 20310
|
||||||
KAFKA_CONSUMER_ENABLED: ${KAFKA_CONSUMER_ENABLED_ANALYTICS:-true}
|
KAFKA_CONSUMER_ENABLED: ${KAFKA_CONSUMER_ENABLED_ANALYTICS:-true}
|
||||||
KAFKA_CONSUMER_CLIENT_ID_PREFIX: ${KAFKA_CONSUMER_CLIENT_ID_PREFIX_ANALYTICS:-vehicle-analytics}
|
KAFKA_CONSUMER_CLIENT_ID_PREFIX: ${KAFKA_CONSUMER_CLIENT_ID_PREFIX_ANALYTICS:-vehicle-analytics}
|
||||||
KAFKA_CONSUMER_MAX_POLL_INTERVAL_MILLIS: ${KAFKA_CONSUMER_MAX_POLL_INTERVAL_MILLIS_ANALYTICS:-900000}
|
KAFKA_CONSUMER_MAX_POLL_INTERVAL_MILLIS: ${KAFKA_CONSUMER_MAX_POLL_INTERVAL_MILLIS_ANALYTICS:-900000}
|
||||||
@@ -199,12 +199,12 @@ services:
|
|||||||
MYSQL_USERNAME: ${MYSQL_USERNAME:-}
|
MYSQL_USERNAME: ${MYSQL_USERNAME:-}
|
||||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-}
|
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-}
|
||||||
ports:
|
ports:
|
||||||
- "${VEHICLE_ANALYTICS_HTTP_PORT:-20300}:20300"
|
- "${VEHICLE_ANALYTICS_HTTP_PORT:-20310}:20310"
|
||||||
networks:
|
networks:
|
||||||
- vehicle-ingest
|
- vehicle-ingest
|
||||||
healthcheck:
|
healthcheck:
|
||||||
<<: *readiness-healthcheck
|
<<: *readiness-healthcheck
|
||||||
test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:20300/actuator/health/readiness >/dev/null"]
|
test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:20310/actuator/health/readiness >/dev/null"]
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
vehicle-ingest:
|
vehicle-ingest:
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ This runbook covers the default production runtimes: GB32960 ingest, JT808 inges
|
|||||||
| JT808 ingest | `:jt808-ingest-app` | Accept JT/T 808 TCP connections on the production receive port, parse raw frames, archive frame bytes, and produce raw/event envelopes to Kafka. | TCP `808`, HTTP `20400` |
|
| JT808 ingest | `:jt808-ingest-app` | Accept JT/T 808 TCP connections on the production receive port, parse raw frames, archive frame bytes, and produce raw/event envelopes to Kafka. | TCP `808`, HTTP `20400` |
|
||||||
| Yutong MQTT ingest | `:yutong-mqtt-app` | Connect to Yutong MQTT, parse subscribed messages, archive payloads, and produce raw/event envelopes to Kafka. | HTTP `20500` |
|
| Yutong MQTT ingest | `:yutong-mqtt-app` | Connect to Yutong MQTT, parse subscribed messages, archive payloads, and produce raw/event envelopes to Kafka. | HTTP `20500` |
|
||||||
| Vehicle history | `:vehicle-history-app` | Consume GB32960/JT808/Yutong MQTT raw/event Kafka records, store compact history rows plus TDengine `raw_frames` `parsedJson`/`metadataJson`/`rawUri`, and expose TDengine-backed history APIs. | HTTP `20200` |
|
| Vehicle history | `:vehicle-history-app` | Consume GB32960/JT808/Yutong MQTT raw/event Kafka records, store compact history rows plus TDengine `raw_frames` `parsedJson`/`metadataJson`/`rawUri`, and expose TDengine-backed history APIs. | HTTP `20200` |
|
||||||
| Vehicle analytics | `:vehicle-analytics-app` | Consume JT808 event Kafka records, calculate daily mileage from reported GPS total mileage, and write metrics to `vehicle_stat_metric`. | HTTP `20300` |
|
| Vehicle analytics | `:vehicle-analytics-app` | Consume JT808 event Kafka records, calculate daily mileage from reported GPS total mileage, and write metrics to `vehicle_stat_metric`. | HTTP `20310` |
|
||||||
|
|
||||||
## Kafka Contract
|
## Kafka Contract
|
||||||
|
|
||||||
@@ -130,9 +130,9 @@ curl -sS http://127.0.0.1:20500/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/liveness
|
||||||
curl -sS http://127.0.0.1:20200/actuator/health/readiness
|
curl -sS http://127.0.0.1:20200/actuator/health/readiness
|
||||||
curl -sS http://127.0.0.1:20300/actuator/health
|
curl -sS http://127.0.0.1:20310/actuator/health
|
||||||
curl -sS http://127.0.0.1:20300/actuator/health/liveness
|
curl -sS http://127.0.0.1:20310/actuator/health/liveness
|
||||||
curl -sS http://127.0.0.1:20300/actuator/health/readiness
|
curl -sS http://127.0.0.1:20310/actuator/health/readiness
|
||||||
```
|
```
|
||||||
|
|
||||||
Expected: each aggregate, liveness, and readiness endpoint returns `{"status":"UP"}` or an equivalent Spring Boot health JSON with top-level status `UP`.
|
Expected: each aggregate, liveness, and readiness endpoint returns `{"status":"UP"}` or an equivalent Spring Boot health JSON with top-level status `UP`.
|
||||||
@@ -185,7 +185,7 @@ Useful HTTP query checks after events are consumed. For `realtime_001.hex`, the
|
|||||||
curl -sS 'http://127.0.0.1:20200/api/event-history/locations?protocol=GB32960&dateFrom=<date-from>&dateTo=<date-to>&vin=LTEST000000000001&limit=10'
|
curl -sS 'http://127.0.0.1:20200/api/event-history/locations?protocol=GB32960&dateFrom=<date-from>&dateTo=<date-to>&vin=LTEST000000000001&limit=10'
|
||||||
curl -sS 'http://127.0.0.1:20200/api/event-history/raw-frames?protocol=GB32960&dateFrom=<date-from>&dateTo=<date-to>&vin=LTEST000000000001&limit=10'
|
curl -sS 'http://127.0.0.1:20200/api/event-history/raw-frames?protocol=GB32960&dateFrom=<date-from>&dateTo=<date-to>&vin=LTEST000000000001&limit=10'
|
||||||
curl -sS 'http://127.0.0.1:20200/api/event-history/gb32960/dictionary'
|
curl -sS 'http://127.0.0.1:20200/api/event-history/gb32960/dictionary'
|
||||||
curl -sS 'http://127.0.0.1:20300/api/vehicle-stat/LTEST000000000001/daily?date=<stat-date>'
|
curl -sS 'http://127.0.0.1:20310/api/vehicle-stat/LTEST000000000001/daily?date=<stat-date>'
|
||||||
```
|
```
|
||||||
|
|
||||||
Expected E2E result when Kafka and all services are running:
|
Expected E2E result when Kafka and all services are running:
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ mvn -pl :gb32960-ingest-app,:jt808-ingest-app,:yutong-mqtt-app,:vehicle-history-
|
|||||||
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' \
|
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' \
|
||||||
| egrep 'gb32960|jt808|yutong|vehicle-history|vehicle-analytics|NAMES'
|
| egrep 'gb32960|jt808|yutong|vehicle-history|vehicle-analytics|NAMES'
|
||||||
|
|
||||||
ss -lntp | egrep ':(808|32960|20100|20200|20300|20400|20500)\b'
|
ss -lntp | egrep ':(808|32960|20100|20200|20310|20400|20500)\b'
|
||||||
|
|
||||||
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/liveness
|
||||||
@@ -68,9 +68,9 @@ 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/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'
|
||||||
curl -sS http://127.0.0.1:20300/actuator/health
|
curl -sS http://127.0.0.1:20310/actuator/health
|
||||||
curl -sS http://127.0.0.1:20300/actuator/health/liveness
|
curl -sS http://127.0.0.1:20310/actuator/health/liveness
|
||||||
curl -sS http://127.0.0.1:20300/actuator/health/readiness
|
curl -sS http://127.0.0.1:20310/actuator/health/readiness
|
||||||
```
|
```
|
||||||
|
|
||||||
预期:五个容器均为运行状态;健康检查为 `UP`;JT808/GB32960 TCP 端口在 ECS 上监听;OpenAPI 中包含通用位置分页查询和 RAW 帧查询接口。history-app 不暴露 `/api/event-history/telemetry/fields`,也不持续写入逐字段宽表。JT808 位置帧中有 GPS 总里程时,`vehicle-analytics-app` 按差值法写入 MySQL `vehicle_stat_metric` 的 `daily_mileage_km` 指标。
|
预期:五个容器均为运行状态;健康检查为 `UP`;JT808/GB32960 TCP 端口在 ECS 上监听;OpenAPI 中包含通用位置分页查询和 RAW 帧查询接口。history-app 不暴露 `/api/event-history/telemetry/fields`,也不持续写入逐字段宽表。JT808 位置帧中有 GPS 总里程时,`vehicle-analytics-app` 按差值法写入 MySQL `vehicle_stat_metric` 的 `daily_mileage_km` 指标。
|
||||||
@@ -83,7 +83,7 @@ curl -sS http://127.0.0.1:20300/actuator/health/readiness
|
|||||||
- `gb32960-ingest-app` 监听 TCP `32960`,HTTP `20100`。
|
- `gb32960-ingest-app` 监听 TCP `32960`,HTTP `20100`。
|
||||||
- `yutong-mqtt-app` 监听 HTTP `20500`。
|
- `yutong-mqtt-app` 监听 HTTP `20500`。
|
||||||
- `vehicle-history-app` 监听 HTTP `20200`。
|
- `vehicle-history-app` 监听 HTTP `20200`。
|
||||||
- `vehicle-analytics-app` 监听 HTTP `20300`。
|
- `vehicle-analytics-app` 监听 HTTP `20310`。
|
||||||
- history 热查询只依赖 Kafka 和 TDengine `raw_frames`;history 不需要共享 archive volume。
|
- history 热查询只依赖 Kafka 和 TDengine `raw_frames`;history 不需要共享 archive volume。
|
||||||
- GB32960/JT808/Yutong MQTT 接入服务可以继续使用 `SINK_ARCHIVE_PATH` 保存原始冷备,但这不是 history API 的实时查询前置条件。
|
- GB32960/JT808/Yutong MQTT 接入服务可以继续使用 `SINK_ARCHIVE_PATH` 保存原始冷备,但这不是 history API 的实时查询前置条件。
|
||||||
|
|
||||||
@@ -111,9 +111,9 @@ curl -sS http://127.0.0.1:20500/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/liveness
|
||||||
curl -sS http://127.0.0.1:20200/actuator/health/readiness
|
curl -sS http://127.0.0.1:20200/actuator/health/readiness
|
||||||
curl -sS http://127.0.0.1:20300/actuator/health
|
curl -sS http://127.0.0.1:20310/actuator/health
|
||||||
curl -sS http://127.0.0.1:20300/actuator/health/liveness
|
curl -sS http://127.0.0.1:20310/actuator/health/liveness
|
||||||
curl -sS http://127.0.0.1:20300/actuator/health/readiness
|
curl -sS http://127.0.0.1:20310/actuator/health/readiness
|
||||||
```
|
```
|
||||||
|
|
||||||
API / Swagger:
|
API / Swagger:
|
||||||
@@ -122,7 +122,7 @@ API / Swagger:
|
|||||||
- GB32960 ingest health: `http://127.0.0.1:20100/actuator/health`
|
- GB32960 ingest health: `http://127.0.0.1:20100/actuator/health`
|
||||||
- Yutong MQTT ingest health: `http://127.0.0.1:20500/actuator/health`
|
- Yutong MQTT ingest health: `http://127.0.0.1:20500/actuator/health`
|
||||||
- History query: `http://127.0.0.1:20200/swagger-ui/index.html`
|
- History query: `http://127.0.0.1:20200/swagger-ui/index.html`
|
||||||
- Analytics metrics: `http://127.0.0.1:20300/swagger-ui/index.html`
|
- Analytics metrics: `http://127.0.0.1:20310/swagger-ui/index.html`
|
||||||
|
|
||||||
## Kafka Topic 验证
|
## Kafka Topic 验证
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ spring:
|
|||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
|
||||||
server:
|
server:
|
||||||
port: ${HTTP_PORT:20300}
|
port: ${HTTP_PORT:20310}
|
||||||
|
|
||||||
springdoc:
|
springdoc:
|
||||||
swagger-ui:
|
swagger-ui:
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class VehicleAnalyticsAppDefaultsTest {
|
|||||||
"spring.config.import[0]",
|
"spring.config.import[0]",
|
||||||
"optional:nacos:${spring.application.name}.${NACOS_CONFIG_FILE_EXTENSION:yml}?group=${NACOS_GROUP:DEFAULT_GROUP}&refreshEnabled=${NACOS_REFRESH_ENABLED:true}")
|
"optional:nacos:${spring.application.name}.${NACOS_CONFIG_FILE_EXTENSION:yml}?group=${NACOS_GROUP:DEFAULT_GROUP}&refreshEnabled=${NACOS_REFRESH_ENABLED:true}")
|
||||||
.containsEntry("spring.cloud.nacos.config.server-addr", "${NACOS_SERVER_ADDR:127.0.0.1:8848}")
|
.containsEntry("spring.cloud.nacos.config.server-addr", "${NACOS_SERVER_ADDR:127.0.0.1:8848}")
|
||||||
|
.containsEntry("server.port", "${HTTP_PORT:20310}")
|
||||||
.containsEntry("lingniu.ingest.vehicle-stat.enabled", "${VEHICLE_STAT_ENABLED:true}")
|
.containsEntry("lingniu.ingest.vehicle-stat.enabled", "${VEHICLE_STAT_ENABLED:true}")
|
||||||
.containsEntry(
|
.containsEntry(
|
||||||
"lingniu.ingest.vehicle-stat.jt808.enabled",
|
"lingniu.ingest.vehicle-stat.jt808.enabled",
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class PortainerComposeResourceLimitsTest {
|
|||||||
assertServiceReadinessHealthcheck(compose, "jt808-ingest-app", "20400");
|
assertServiceReadinessHealthcheck(compose, "jt808-ingest-app", "20400");
|
||||||
assertServiceReadinessHealthcheck(compose, "yutong-mqtt-app", "20500");
|
assertServiceReadinessHealthcheck(compose, "yutong-mqtt-app", "20500");
|
||||||
assertServiceReadinessHealthcheck(compose, "vehicle-history-app", "20200");
|
assertServiceReadinessHealthcheck(compose, "vehicle-history-app", "20200");
|
||||||
assertServiceReadinessHealthcheck(compose, "vehicle-analytics-app", "20300");
|
assertServiceReadinessHealthcheck(compose, "vehicle-analytics-app", "20310");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -123,7 +123,7 @@ class PortainerComposeResourceLimitsTest {
|
|||||||
String runbook = Files.readString(repositoryRoot()
|
String runbook = Files.readString(repositoryRoot()
|
||||||
.resolve("docs/operations/gb32960-service-split-runbook.md"));
|
.resolve("docs/operations/gb32960-service-split-runbook.md"));
|
||||||
|
|
||||||
for (String httpPort : List.of("20100", "20400", "20500", "20200", "20300")) {
|
for (String httpPort : List.of("20100", "20400", "20500", "20200", "20310")) {
|
||||||
assertThat(runbook)
|
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/liveness")
|
||||||
.contains("curl -sS http://127.0.0.1:" + httpPort + "/actuator/health/readiness");
|
.contains("curl -sS http://127.0.0.1:" + httpPort + "/actuator/health/readiness");
|
||||||
@@ -149,7 +149,7 @@ class PortainerComposeResourceLimitsTest {
|
|||||||
String runbook = Files.readString(repositoryRoot()
|
String runbook = Files.readString(repositoryRoot()
|
||||||
.resolve("docs/operations/vehicle-ingest-tdengine-verification.md"));
|
.resolve("docs/operations/vehicle-ingest-tdengine-verification.md"));
|
||||||
|
|
||||||
for (String httpPort : List.of("20100", "20400", "20500", "20200", "20300")) {
|
for (String httpPort : List.of("20100", "20400", "20500", "20200", "20310")) {
|
||||||
assertThat(runbook)
|
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/liveness")
|
||||||
.contains("curl -sS http://127.0.0.1:" + httpPort + "/actuator/health/readiness");
|
.contains("curl -sS http://127.0.0.1:" + httpPort + "/actuator/health/readiness");
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ class WoodpeckerPipelineTest {
|
|||||||
String dockerfile = Files.readString(repositoryRoot().resolve("Dockerfile"));
|
String dockerfile = Files.readString(repositoryRoot().resolve("Dockerfile"));
|
||||||
|
|
||||||
assertThat(dockerfile)
|
assertThat(dockerfile)
|
||||||
.contains("EXPOSE 20100 20200 20300 20400 20500 32960 808")
|
.contains("EXPOSE 20100 20200 20310 20400 20500 32960 808")
|
||||||
|
.doesNotContain("20300")
|
||||||
.doesNotContain("10808")
|
.doesNotContain("10808")
|
||||||
.doesNotContain("8089");
|
.doesNotContain("8089");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user