部署模式选择
eventd v3 的三个模块有不同的部署方式:
| 模块 | 部署方式 | 理由 |
|---|---|---|
| eventd-cleansing | JAR + systemd / Docker | Kafka Streams 是库,不是集群 |
| eventd-analytics | Flink Standalone / Docker | Flink 作业提交到集群 |
| eventd-panel | Docker / K8s Deployment | 无状态 Web 服务 |
Standalone 部署
Flink Standalone 集群
# 1. JobManager
flink-daemon.sh start jobmanager
# 2. TaskManager(每台机器)
flink-daemon.sh start taskmanager
# 3. 提交作业
flink run \
--class com.plume.eventd.AnalyticsJob \
--parallelism 4 \
--detached \
eventd-analytics-1.0.jar
# 4. 查看作业
flink list
TaskManager 内存配置
# flink-conf.yaml
taskmanager.memory.process.size: 4g # TM 总内存
taskmanager.memory.managed.fraction: 0.4 # 40% 给托管内存(RocksDB)
taskmanager.memory.network.fraction: 0.15 # 网络缓冲
taskmanager.memory.jvm-overhead.fraction: 0.2 # JVM 开销
managed / network 的比例是相对 Total Flink Memory,jvm-overhead 是相对进程总内存;直接相加会算错,完整的拆分见 14.2 故障排查
。
Docker 容器化
基础镜像统一用 Java 17。Flink 1.20 官方验证的是 Java 11 和 17;JDK 21 及以上属于未验证组合,可能在提交作业或反序列化时失败。Java 应用用 eclipse-temurin:17-jdk-alpine,Flink 侧直接用官方镜像的 flink:1.20-scala_2.12-java17 变体,别自己往 flink:1.20-scala_2.12(默认 Java 11)里换 JDK。
eventd-cleansing Dockerfile
FROM eclipse-temurin:17-jdk-alpine
WORKDIR /app
COPY target/eventd-cleansing-1.0.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
eventd-analytics Dockerfile
# 直接用 Flink 官方镜像:里面的 flink 客户端、JAVA_HOME 和依赖都已就绪
FROM flink:1.20-scala_2.12-java17
WORKDIR /opt/flink/usrlib
COPY target/eventd-analytics-1.0.jar app.jar
# 提交作业(假设 JobManager 在 flink-jobmanager:8081)
CMD ["flink", "run", \
"-m", "flink-jobmanager:8081", \
"-c", "com.plume.eventd.AnalyticsJob", \
"app.jar"]
不要在 eclipse-temurin 基础镜像里临时下载 Flink 发行包:-alpine 镜像默认没有 wget,而且每次启动都要重新下载,构建结果不可复现。
eventd-panel Dockerfile
FROM eclipse-temurin:17-jdk-alpine
WORKDIR /app
COPY target/eventd-panel-1.0.jar app.jar
EXPOSE 8083
ENTRYPOINT ["java", "-jar", "app.jar"]
docker-compose.yml
services:
kafka:
image: confluentinc/cp-kafka:7.8.0
hostname: kafka
ports:
- "9092:29092" # 宿主机 9092 → 容器内 PLAINTEXT_HOST 监听
environment:
# 7.4 起默认 KRaft,不再需要单独的 Zookeeper 容器。
# 这是单节点演示配置;生产至少 3 个 controller。
CLUSTER_ID: MkU3OEVBNTcwNTJENDM2Qk
KAFKA_NODE_ID: 1
KAFKA_PROCESS_ROLES: broker,controller
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:29093
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
# 两个数据监听器:容器之间用 kafka:9092,宿主机用 localhost:9092。
# 只配一个监听器时,另一侧拿到的是不可解析的地址,客户端会一直重连
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:29093,PLAINTEXT_HOST://0.0.0.0:29092
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
redis:
image: redis:7-alpine
ports:
- "6379:6379"
flink-jobmanager:
image: flink:1.20-scala_2.12-java17
ports:
- "8081:8081"
command: jobmanager
environment:
- JOB_MANAGER_RPC_ADDRESS=flink-jobmanager
flink-taskmanager:
image: flink:1.20-scala_2.12-java17
command: taskmanager
environment:
- JOB_MANAGER_RPC_ADDRESS=flink-jobmanager
- TASK_MANAGER_NUMBER_OF_TASK_SLOTS=4
cleansing:
build: ./eventd-cleansing
environment:
# 容器内不能写 localhost:localhost 指向容器自己
- KAFKA_BOOTSTRAP_SERVERS=kafka:9092
depends_on:
- kafka
analytics:
build: ./eventd-analytics
environment:
- KAFKA_BOOTSTRAP_SERVERS=kafka:9092
- REDIS_HOST=redis
depends_on:
- kafka
- redis
- flink-jobmanager
panel:
build: ./eventd-panel
environment:
- REDIS_HOST=redis
- SPRING_DATA_REDIS_HOST=redis
ports:
- "8083:8083"
depends_on:
- redis
depends_on 只保证容器的启动顺序,不保证 Kafka 已能建 Topic、JobManager 已能接受提交;analytics 容器第一次 flink run 很可能因为 JM 还没起来而失败。生产环境要配 healthcheck + restart: on-failure,或者在启动脚本里轮询 http://flink-jobmanager:8081/overview 直到就绪。
Savepoint 与作业升级
触发 Savepoint
# 1. 获取当前作业 ID
flink list
# 2. 触发 Savepoint
flink savepoint <job-id> file:///var/flink/savepoints
# 3. 停止作业
flink cancel <job-id>
# 4. 从 Savepoint 启动新版本
flink run \
--fromSavepoint file:///var/flink/savepoints/savepoint-xxxxx \
--class com.plume.eventd.AnalyticsJob \
eventd-analytics-1.1.jar
Savepoint 升级注意事项
兼容的变更:
✅ 新增算子(新增分支)
✅ 修改业务逻辑(不改变状态类型)
✅ 调整并行度
不兼容的变更:
❌ 删除算子
❌ 修改 KeyedState 的类型
❌ 修改窗口类型
如果变更不兼容:
- 先确认这部分状态可以丢,再考虑
--allowNonRestoredState。它会让 Flink 跳过无法映射的状态,作业能起来,但计数类状态会从 0 重新累计,而且只在日志里留一条警告。 - 对账、计费这类不能丢状态的场景,正确做法是让新作业从明确的 Kafka offset 重放,重算结果,而不是静默丢弃旧状态。
配置分层
eventd v3 的环境配置:
config/
├── application-dev.yaml # 开发环境
├── application-staging.yaml # 测试环境
└── application-prod.yaml # 生产环境
不同环境的差异:
| 配置 | dev | staging | prod |
|---|---|---|---|
| Kafka broker | localhost:9092 | kafka-staging:9092 | kafka-prod:9092 |
| Flink parallelism | 1 | 4 | 12 |
| Checkpoint interval | 60s | 30s | 30s |
| Redis | localhost:6379 | redis-staging:6379 | redis-prod:6379 |
| SSE connections | 100 | 500 | 5000 |
启动时指定环境:
# -D 必须写在 -jar 之前,否则会被当成传给应用的参数而失效
java -Dspring.profiles.active=prod -jar app.jar
运维检查清单
每日检查:
# Flink 作业运行状态
curl http://flink-jobmanager:8081/jobs
# Kafka Topic 消费进度(lag)
kafka-consumer-groups.sh --bootstrap-server kafka:9092 \
--describe --group eventd-analytics
# Redis 内存使用
redis-cli INFO memory
# 面板 HTTP 健康检查
curl http://panel:8083/api/health
每周检查:
# Checkpoint 大小趋势
# → 持续增长说明 TTL 未生效或状态泄漏
# 死信队列消息数
kafka-run-class.sh kafka.tools.GetOffsetShell \
--bootstrap-server kafka:9092 --topic eventd-dead-letter
# Flink 反压状态(Web UI)
监控告警
# prometheus/alerts.yml
groups:
- name: eventd
rules:
- alert: FlinkCheckpointFailed
# 该指标以 Gauge 暴露累计失败数(实现类是 FailedCheckpointsCounter
# implements Gauge<Long>),不是 Counter;直接写 > 0 会让告警永远不恢复。
# 值单调递增,所以 increase() 可用;看最近 10 分钟有没有新增失败
expr: increase(flink_jobmanager_job_numberOfFailedCheckpoints[10m]) > 0
for: 1m
- alert: KafkaConsumerLag
# kafka_exporter 的指标名与标签;用 JMX exporter 时名字不同。
# 标签是 consumergroup,不是 group;写成 group= 会得到空向量
expr: kafka_consumergroup_lag{consumergroup="eventd-analytics"} > 10000
for: 5m
- alert: RedisMemoryHigh
# redis_exporter 没有直接给百分比,需要自己算;
# 没配 maxmemory 时 redis_memory_max_bytes 为 0,除法会得到 NaN、告警永远不触发
expr: redis_memory_max_bytes > 0
and redis_memory_used_bytes / redis_memory_max_bytes * 100 > 80
for: 5m
- alert: PanelConnectionsHigh
expr: eventd_panel_sse_connections > 4500
for: 1m
小结
| 操作 | 命令/方法 |
|---|---|
| 提交作业 | flink run --class ... |
| 触发 Savepoint | flink savepoint <job-id> |
| 恢复作业 | flink run --fromSavepoint ... |
| 停止作业 | flink cancel <job-id> |
| 查看日志 | JobManager/TaskManager 日志文件、Web UI 或 docker logs |
| 健康检查 | Web UI / REST API |
下一节 12.3 v3 验收 :全链路可运行、指标正确性、延迟达标。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。