3. 环境搭建

说实话,学实时数据流,最劝退的就是环境搭建。

Kafka、Flink、Redis,这三个东西单独装都不算难,但要让它们在一个局域网里好好配合,端口不冲突、版本不打架、网络能互通——我当年第一次搞的时候,折腾了整整一个周末。后来我学乖了,直接用 Docker Compose,一条命令拉起所有服务。

这一章,我就带你走一遍我的「标准配置」。你跟着做,半小时内就能跑起来。

本章目标: 用 Docker Compose 一键部署 Kafka(含 Zookeeper)+ Flink(JobManager + TaskManager)+ Redis,并验证各服务连通性。

3.1 为什么选 Docker Compose?

你可能会问:我直接在本地装不行吗?

行,但我不建议。原因有三:

  • 隔离性:每个服务跑在独立容器里,不会污染你的宿主机。我曾经在 Mac 上装 Kafka,结果和本地的 Java 版本冲突,修了半天。
  • 可复现:写一个 docker-compose.yml,团队里任何人拉下来都能跑出一模一样的环境。你想想看,这比写十页部署文档靠谱多了。
  • 易清理:docker-compose down -v 一键清空,不留痕迹。做实验、搞坏了,重来就是几秒钟的事。

说白了,Docker Compose 就是给本地开发环境用的「基础设施即代码」。你值得拥有。

3.2 整体架构图

先看一眼我们要搭的东西长什么样:

Docker Compose 实时数据开发环境架构 Zookeeper 端口: 2181 Kafka Broker 端口: 9092 Flink JobManager 端口: 8081 (UI) Flink TaskManager 端口: 6121-6123 Redis 端口: 6379 数据流 结果写入 💡 说明: Kafka 依赖 Zookeeper 做元数据管理;Flink 从 Kafka 消费数据,处理后写入 Redis。 所有服务通过 Docker 内部网络通信,宿主机通过映射端口访问。

3.3 准备工作

在开始之前,确认你的机器上已经装好了:

  • Docker:20.10 以上版本。用 docker --version 检查。
  • Docker Compose:v2 以上。用 docker compose version 检查(注意是空格,不是横线)。

如果你还没装,去官网下载 Docker Desktop 就行,它自带 Compose。我个人习惯用 macOS,但这套配置在 Linux 和 Windows WSL2 上同样跑得很顺。

3.4 编写 docker-compose.yml

这是核心文件。我直接给你一份我项目里常用的版本,注释都写好了:

version: '3.8'

services:
  # ---------- Zookeeper ----------
  zookeeper:
    image: confluentinc/cp-zookeeper:7.4.0
    container_name: zookeeper
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
    ports:
      - "2181:2181"
    networks:
      - realtime-net

  # ---------- Kafka ----------
  kafka:
    image: confluentinc/cp-kafka:7.4.0
    container_name: kafka
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
    networks:
      - realtime-net

  # ---------- Flink JobManager ----------
  flink-jobmanager:
    image: flink:1.17.1-scala_2.12
    container_name: flink-jobmanager
    ports:
      - "8081:8081"
    command: jobmanager
    environment:
      - JOB_MANAGER_RPC_ADDRESS=flink-jobmanager
    networks:
      - realtime-net

  # ---------- Flink TaskManager ----------
  flink-taskmanager:
    image: flink:1.17.1-scala_2.12
    container_name: flink-taskmanager
    depends_on:
      - flink-jobmanager
    command: taskmanager
    environment:
      - JOB_MANAGER_RPC_ADDRESS=flink-jobmanager
      - TASK_MANAGER_NUMBER_OF_TASK_SLOTS=2
    networks:
      - realtime-net

  # ---------- Redis ----------
  redis:
    image: redis:7.2-alpine
    container_name: redis
    ports:
      - "6379:6379"
    networks:
      - realtime-net

networks:
  realtime-net:
    driver: bridge
💡 我的习惯: 把 Kafka 和 Flink 的版本固定写死,不要用 latest。我曾经被 latest 坑过一次——某天拉下来发现 API 变了,整个项目跑不起来。版本锁定,是专业选手的基本素养。

3.5 启动服务

把上面的内容保存为 docker-compose.yml,然后在终端里执行:

# 启动所有服务(后台运行)
docker compose up -d

# 查看容器状态
docker compose ps

# 查看实时日志(按 Ctrl+C 退出)
docker compose logs -f

启动后,你会看到类似这样的输出:

NAME                 IMAGE                              STATUS   PORTS
zookeeper            confluentinc/cp-zookeeper:7.4.0    Up       2181/tcp
kafka                confluentinc/cp-kafka:7.4.0        Up       0.0.0.0:9092->9092/tcp
flink-jobmanager     flink:1.17.1-scala_2.12            Up       0.0.0.0:8081->8081/tcp
flink-taskmanager    flink:1.17.1-scala_2.12            Up       6121-6123/tcp
redis                redis:7.2-alpine                   Up       0.0.0.0:6379->6379/tcp

看到所有服务都是 Up 状态,就说明成功了。

3.6 验证连通性

服务跑起来了,但能不能互相通信?我们来验证一下。

3.6.1 验证 Kafka

进入 Kafka 容器,创建一个测试主题:

docker exec -it kafka kafka-topics --create \
  --topic test-topic \
  --bootstrap-server localhost:9092 \
  --partitions 1 \
  --replication-factor 1

然后启动一个生产者,随便发几条消息:

docker exec -it kafka bash -c 'echo "hello realtime" | kafka-console-producer --topic test-topic --bootstrap-server localhost:9092'

再启动消费者看看能不能收到:

docker exec -it kafka kafka-console-consumer \
  --topic test-topic \
  --from-beginning \
  --bootstrap-server localhost:9092

如果看到 hello realtime 打印出来,Kafka 就通了。

3.6.2 验证 Redis

# 进入 Redis 容器
docker exec -it redis redis-cli

# 设置一个键值对
127.0.0.1:6379> set mykey "hello from flink"
OK

# 读取
127.0.0.1:6379> get mykey
"hello from flink"

# 退出
127.0.0.1:6379> exit

3.6.3 验证 Flink UI

打开浏览器,访问 http://localhost:8081。你应该能看到 Flink 的 Web Dashboard,里面显示有一个 TaskManager 在线,2 个 Slot 可用。

⚠️ 避坑指南: 我曾经在 Windows 上遇到 Flink UI 打不开的情况,原因是 Docker Desktop 的端口映射没生效。解决方案:在 Docker Desktop 设置里把 Resources → Network 的 DNS 改成 8.8.8.8,然后重启 Docker。

3.7 常用操作速查表

开发过程中,你肯定会频繁用到这些命令。我整理了一张表,建议你收藏:

操作 命令
启动所有服务 docker compose up -d
停止所有服务 docker compose down
停止并删除数据卷 docker compose down -v
查看日志 docker compose logs -f [服务名]
重启某个服务 docker compose restart [服务名]
进入容器 docker exec -it [容器名] bash

3.8 本章小结

到这里,你的本地开发环境就搭好了。我们有了:

  • Kafka:消息队列,负责接收和缓存实时数据流。
  • Flink:流计算引擎,负责处理数据。
  • Redis:高速缓存,负责存储计算结果。

这三个服务通过 Docker 内部网络互联,你在宿主机上通过映射端口就能访问。接下来几章,我们会基于这个环境,一步步写出第一个实时数据管道。

嗯,环境搭好了,心里就踏实了。后面的事,咱们慢慢来。