介绍
一个订单被创建,另一个订单被创建,然后第一个订单已付款。当前状态表可能只显示每个订单的最新状态。事件(event)描述发生过的事情,因此这三个事实都可以作为历史保留价值。响应新订单的系统需要在应用之间传递这些事实。
Apache Kafka 存储并传递事件记录。生产者(producer)发送记录,代理(broker)是接收并存储记录的服务器,主题(topic)为记录流命名,消费者(consumer)读取记录。Kafka 能连接运行时间或速度不同的应用。其他处理工具可以根据事件计算报表;本课程先关注可靠传递和读取进度。
你将创建主题,在独立终端中观察生产者和消费者,并在第一个消费者退出后再次读取相同事件。预配置的单代理环境使用一份副本;集群部署是独立主题。前六个活动只要求基本终端操作。后面的 Python 客户端活动要求函数、循环、字典、JSON 和运行脚本;Python 学习路径 可帮助准备。Java、Hadoop、Hive、Spark 和外部账号都不是先修要求。请使用终端服务。
为订单事件创建存储位置
在这一步中,你将确认预配置 Kafka 服务能够响应,并创建主题。把第一个 Shell 保留为终端 A。进入工作目录:
## Terminal A
cd /home/labex/project
命令行客户端已经安装。--bootstrap-server 提供初始代理地址,用来发现集群。这里 localhost:9092 是预配置的本地服务,不是外部账号。列出主题,确认真实代理响应:
## Terminal A
kafka-topics.sh --bootstrap-server localhost:9092 --list
干净的教学环境可能还没有应用主题。创建 orders-first。主题包含一个或多个分区(partition),即存储记录的有序日志。先使用一个分区,让首次顺序容易理解。--replication-factor 1 符合预配置的单代理环境:
## Terminal A
kafka-topics.sh --bootstrap-server localhost:9092 --create --topic orders-first --partitions 1 --replication-factor 1
检查新主题:
## Terminal A
kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic orders-first
找到主题名、PartitionCount: 1 和 ReplicationFactor: 1。ID、leader 标识和格式可能变化。创建主题建立了存储目标,还没有发送订单,也没有安装另一台服务器。
短期运行的生产者和消费者客户端启动和退出时,代理将持续运行。接下来,你将利用这个分离关系观察事件到达。
观察一个客户端接收另一个客户端发送的内容
在这一步中,你将在一个终端让消费者等待,并从另一个发送三条记录。终端服务通过终端会话管理器 tmux 保留 Shell。第二个浏览器连接最初显示同一个持久会话。为终端 B 创建独立命名的 Shell 会话,让两个客户端各有提示符。
在终端 A 创建分离会话。-d 保持当前终端选中,-s 命名新会话,-c 选择起始目录。这会创建 Shell,不是另一个 Kafka 代理:
## Terminal A
tmux new-session -d -s kafka-b -c /home/labex/project
在第二个浏览器标签页打开同一个终端服务,保留终端 A。把新标签页称为终端 B,将该连接切换到准备好的会话:
## Terminal B
tmux switch-client -t kafka-b
切换后,在只有 Shell 活动时,按一次 Ctrl-C 清除未提交的终端输入。确认会话名:
## Terminal B
tmux display-message -p '#S'
预期为 kafka-b。终端 A 保留原会话,两个 Shell 访问相同虚拟机文件。切换浏览器标签页时保持这些角色。如果练习中已经创建命名会话,请复用,不要重复创建。
在终端 B 启动下面的消费者。它等待直到读到三条记录,然后自动退出。--from-beginning 请求这个新消费者从保留记录的开头读取;--max-messages 3 限制工作量,--timeout-ms 30000 限制空闲等待。管道把标准输出传给 tee,后者既显示内容,也保存本地副本:
## Terminal B
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic orders-first --from-beginning --max-messages 3 --timeout-ms 30000 | tee /home/labex/project/output/received-events.txt
让终端 B 等待。切换到终端 A,在 30 秒空闲限制内发送批次。如果发送前限制已到,请在终端 B 再次启动相同消费者命令,再切换回来发送。如果事件已经发出,只重跑消费者检查保留的三条记录;再次发送生产者批次会追加重复记录:
## Terminal A
printf '%s\n' 'order-1001 created' 'order-1002 created' 'order-1001 paid' | kafka-console-producer.sh --bootstrap-server localhost:9092 --topic orders-first
printf 打印每个带引号文本值及其后的换行。管道将这些行提供给生产者;这个控制台生产者把每行视为一条事件记录。printf 完成时输入流关闭,生产者完成待发送内容后退出。无需在交互生产者提示符中输入。
回到终端 B,三条数据行应该是:
order-1001 created
order-1002 created
order-1001 paid
终端中也可能出现已处理消息数或客户端诊断。保存的文件应包含三个事件值。order-1001 的两个事实是独立记录;paid 事件没有覆盖之前的 created 事件。
消费者通常在三条消息后返回提示符。如果意外启动无界客户端,在它自己的终端按 Ctrl-C 会停止该客户端,不停止代理,也不删除主题。这里的限制让正常流程无需手动中断即可结束。
使用新消费者读取保留事件
在这一步中,你将检查读取是否移除了事件。第一个消费者已退出。预测独立新消费者从保留记录开头会看到什么:相同的三条记录。
在终端 B 运行新的有界消费者,将第二次读取单独保存:
## Terminal B
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic orders-first --from-beginning --max-messages 3 --timeout-ms 30000 | tee /home/labex/project/output/replayed-events.txt
预期在这个单分区内,以相同顺序读到相同三个值。你没有发送另一批数据。从终端 A 查看两个本地观察结果:
## Terminal A
cat /home/labex/project/output/received-events.txt
## Terminal A
cat /home/labex/project/output/replayed-events.txt
两者都应包含全部三个原始事件。消费与存储保留是独立的:读取不会从主题中移除记录。首次实验使用新的控制台消费者。之后你将学习命名消费者组如何保存读取进度,以及为什么从头读取选项不会覆盖已提交的有效位置。
两个短期客户端退出后,Kafka 仍让事件历史可用。接下来,你将检查主题属性,了解保留配置如何独立于消费进度影响存储策略。
总结
你认识了 Kafka 的事件传递职责,创建单分区主题,并观察独立生产者和消费者客户端交换三个订单事件。第一个消费者退出后,新消费者读取到相同保留历史,说明读取与删除是不同操作。接下来,你将检查主题分区、副本与保留属性。



