Kafka基础
定义 :分布式发布/订阅消息队列系统
核心概念:
- 生产者→Topic→消费者
- Broker:Kafka服务器节点
- Partition:Topic的分区(提高并发)
- Replication:副本(保证可靠性)
消息队列价值:
- 解耦生产消费
- 流量削峰(如秒杀系统)
- 异步通信
- 数据缓冲
排错要点
- Topic不匹配:Flume配置的topic必须与消费者一致
- 服务未启动:确保ZooKeeper和Kafka已运行(jps检查)
- 配置文件路径:所有路径需使用绝对路径
- 网络地址:建议统一使用localhost避免解析问题
关键理解
- Flume作用:自动化数据采集(文件→Kafka)
- Kafka直接通信:适合手动测试
- 配置一致性:Topic名称、服务器地址必须匹配
注:实际环境需根据具体路径和主机名调整配置
Kafka + Flume 实操详情记录(略繁琐,包含错误和排查记录)
以下是为你整理的Kafka课堂笔记完整梳理与补充,结构清晰、内容详实,适合学生复习使用。
Kafka 课堂笔记
一、Kafka 定义
Kafka 是一个分布式 的、基于发布/订阅模式的消息队列系统。
数据流转过程:
生产者 → 消息队列(MQ) → 消费者
-
生产者不断产生数据
-
数据被放入消息队列
-
消费者从队列中读取并处理数据
二、消息队列的作用
以"双11秒杀"为例:
商品库存仅 1000 件,但每秒并发请求可达数万甚至数十万。
所有请求进入队列,先进先出,前 1000 个成功处理,其余直接返回"库存不足"。
消息队列的优点:
| 特点 | 说明 |
|---|---|
| 解耦 | 生产者和消费者可独立变化,只需遵循相同接口 |
| 可恢复性 | 部分组件失效不影响整体,降低耦合度 |
| 缓冲 | 生产速率与消费速率可以不一致,队列起到缓冲作用 |
| 灵活性 & 峰值处理能力 | 生产速率过高时,数据堆积在队列中,后期慢慢消费,系统不会崩溃 |
| 异步通信 | 任务拆分为多个步骤并行执行,互不影响;即使消息未被及时消费,仍保留在队列中,随时可拉取 |
三、消息队列的模式
1. 点对点模式
-
一个生产者 → 一个队列 → 一个消费者
-
消息被消费后通常从队列中移除
2. 发布/订阅模式(点对组模式)
-
一个生产者 → 一个队列 → 多个消费者(消费组)
-
消息消费后仍保留在队列中,可被多个消费者重复消费
四、Kafka 核心角色
| 角色 | 说明 |
|---|---|
| Producer | 消息生产者,将数据发送到 Kafka 集群 |
| Consumer | 消息消费者,从 Kafka 读取数据 |
| Consumer Group (CG) | 多个消费者组成一个组,共同消费某个 Topic |
| Broker | 一台 Kafka 服务器就是一个 Broker,多个 Broker 组成集群 |
| Topic | 消息队列,生产者发送数据的目标,消费者订阅的对象 |
| Partition | Topic 的分区,用于水平扩展,提高并发能力 |
| Replication | 副本,保证数据可靠性,防止 Broker 宕机导致数据丢失 |
| Leader | 分区的主节点,负责读写 |
| Follower | 分区的从节点,同步 Leader 数据,Leader 宕机后可选举为新 Leader |
五、Kafka 启动(前置条件)
1. 启动 Hadoop(可选,某些环境依赖)
2. 启动 ZooKeeper
bash
bash
cd $ZOOKEEPER_HOME
bin/zkServer.sh start
3. 启动 Kafka
bash
bash
cd $KAFKA_HOME
bin/kafka-server-start.sh -daemon config/server.properties
4. 验证启动
bash
bash
jps
# 应看到 Kafka 进程
六、Kafka 常用命令(面向 Topic)
| 操作 | 命令示例 |
|---|---|
| 创建 Topic | bin/kafka-topics.sh --zookeeper localhost:2181 --create --replication-factor 1 --partitions 1 --topic a2608 |
| 查看所有 Topic | bin/kafka-topics.sh --zookeeper localhost:2181 --list |
| 删除 Topic | bin/kafka-topics.sh --zookeeper localhost:2181 --delete --topic a2608 |
| 修改 Topic(如增加分区) | bin/kafka-topics.sh --zookeeper localhost:2181 --alter --topic a2608 --partitions 3 |
| 查看 Topic 详情 | bin/kafka-topics.sh --zookeeper localhost:2181 --describe --topic a2608 |
生产与消费消息
| 操作 | 命令 |
|---|---|
| 生产者(发送消息) | bin/kafka-console-producer.sh --broker-list localhost:9092 --topic a2608 |
| 消费者(接收消息) | bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608 |
笔记原文
往队列中发送消息:--a窗口
bin/kafka-console-producer.sh --broker-list localhost:9092 --topic a2608
消费指定队列中的消息:--b窗口
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608
✅ 在一个窗口输入消息,另一个窗口应能实时看到消息
七、Kafka + Flume 整合实战(生产 → 消费)
目标:通过 Flume 监控日志文件,将数据发送到 Kafka,再由 Kafka 消费者实时消费
步骤:
1. 创建模拟日志文件
bash
bash
mkdir -p /opt/module/flume/data/
touch /opt/module/flume/data/flume.log
创建模拟日志文件 在哪创建呢
我的意思在是Linux中创建,还是Hadoop中创建。还是哪里呢
明白了!你的问题是:在哪个系统/环境中执行创建命令。
答案:在 Linux 系统 中创建
具体来说:
执行位置
Linux 操作系统(通常是 CentOS、Ubuntu 等发行版)
通过 终端 / Shell 命令行 执行
就是你安装 Kafka、Flume 的那台 Linux 服务器
详细说明
环境 是否在这里创建 说明 Linux ✅ 是 直接在 Linux 终端执行 mkdir、touch、echo命令Hadoop ❌ 否 Hadoop 是分布式文件系统(HDFS),这里的文件是普通的 Linux 本地文件,不是 HDFS 上的文件 ZooKeeper ❌ 否 ZooKeeper 是协调服务,不用于创建日志文件 Kafka ❌ 否 Kafka 是消息队列,不负责创建日志文件 判断依据
注意 Flume 配置文件中的命令:
bash
a1.sources.r1.command = tail -f /opt/module/flume/data/flume.log
tail -f是 Linux 系统命令 ,监控的是 Linux 本地文件系统 中的文件,而不是 HDFS 上的文件。
完整操作流程
bash
bash# 1. 在 Linux 终端执行(不是 Hadoop 的 hdfs 命令) mkdir -p /opt/module/flume/data/ touch /opt/module/flume/data/flume.log # 2. 查看文件是否创建成功 ls -l /opt/module/flume/data/flume.log # 3. 向文件写入内容(模拟日志产生) echo 111 >> /opt/module/flume/data/flume.log简单记忆
Linux 本地文件系统 ← 创建日志文件
HDFS ← 存储大数据文件(如 Hadoop 处理的数据)
两者是不同的,不要混淆。
2. 编写 Flume 作业配置文件
路径:/opt/module/flume/job/flume-kafka.conf
properties
bash
# define
a1.sources = r1
a1.sinks = k1
a1.channels = c1
# source
a1.sources.r1.type = exec
a1.sources.r1.command = tail -f /opt/module/flume/data/flume.log
# sink (Kafka)
a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
a1.sinks.k1.kafka.bootstrap.servers = node100:9092
a1.sinks.k1.kafka.topic = a2608
a1.sinks.k1.kafka.flumeBatchSize = 20
a1.sinks.k1.kafka.producer.acks = 1
a1.sinks.k1.kafka.producer.linger.ms = 1
# channel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
# bind
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
已经在Hadoop中了,怎么退出到Linux环境
在 Hadoop 环境中,你很可能已经进入了 HDFS 的交互界面 或正在使用 Hadoop 命令行的某个子 shell。退出到普通 Linux 环境的方法如下:
常见情况及退出方法
情况1:你正在使用
hdfs dfs命令(正常情况)
判断 :提示符仍然是
[user@hostname ~]$这样的 Linux 格式结论:你本来就在 Linux 环境中,只是执行了 Hadoop 命令
操作 :无需退出 ,直接执行
mkdir -p /opt/module/flume/data/即可
情况2:你进入了 HDFS 的交互式 Shell
bash
# 可能你执行了类似这样的命令 hdfs dfs -ls / # 或者进入了某个交互工具
判断 :提示符变成了
hdfs>或>或其他特殊提示符退出方法:
bash
exit # 或按 Ctrl + C # 或按 Ctrl + D
情况3:你通过
ssh进入了 Hadoop 节点
判断:提示符中包含其他主机名
退出方法:
bash
exit # 或按 Ctrl + D
情况4:你正在使用
hadoop fs -ls /等命令后
结论:命令执行完自动回到 Linux 环境
操作:直接继续输入 Linux 命令即可
快速验证当前位置
bash
# 查看当前所在目录(应该是 Linux 路径,不是 HDFS 路径) pwd # 查看提示符格式 # Linux 提示符通常是:[user@hostname ~]$ # 如果看到 > 或 hdfs> 等,说明在子 shell 中
最简单的解决方案
如果搞不清楚状态,直接执行:
bash
# 连续按几次 Ctrl + C(中断当前操作) # 然后按 Ctrl + D(退出可能的子 shell) # 重复 2-3 次,直到回到正常的 Linux 提示符或者直接关闭当前终端窗口,重新打开一个新终端连接 Linux 服务器。
正常情况下的提示符示例
bash
[root@node100 ~]$ # 这是 Linux 环境在这个环境下直接执行:
bash
mkdir -p /opt/module/flume/data/ touch /opt/module/flume/data/flume.log完全没有问题!
3. 启动 Kafka 消费者(等待数据)
bash
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608
启动 Kafka 消费者(等待数据)提示没有那个文件或目录
这个错误说明你当前所在的目录不对 ,系统找不到
bin/kafka-console-consumer.sh这个脚本。
原因
bin/kafka-console-consumer.sh是一个相对路径 ,需要你在 Kafka 的安装根目录下执行。
解决方法
步骤1:找到 Kafka 安装目录
bash
# 查找 Kafka 安装位置 find / -name "kafka-console-consumer.sh" 2>/dev/null # 或者常见安装路径 ls /opt/module/kafka/bin/ ls /usr/local/kafka/bin/ ls /home/kafka/bin/步骤2:进入 Kafka 根目录
bash
# 根据你找到的路径,进入 Kafka 根目录 # 假设 Kafka 安装在 /opt/module/kafka cd /opt/module/kafka步骤3:确认目录结构正确
bash
# 应该能看到 bin 目录 ls -l # 输出示例: # bin/ config/ libs/ logs/ ...步骤4:执行命令
bash
# 现在可以正确执行了 bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608
或者使用绝对路径
bash
# 不切换目录,直接用完整路径 /opt/module/kafka/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608
验证 Kafka 是否真的安装了
bash
# 检查 Kafka 进程是否运行 jps | grep Kafka # 如果没有输出,说明 Kafka 没有启动,需要先启动 cd $KAFKA_HOME bin/kafka-server-start.sh -daemon config/server.properties
设置环境变量(推荐)
为了避免每次都切换目录,可以配置环境变量:
bash
bash# 编辑配置文件 vim ~/.bashrc # 添加以下内容(根据你的实际路径修改) export KAFKA_HOME=/opt/module/kafka export PATH=$PATH:$KAFKA_HOME/bin # 生效 source ~/.bashrc # 之后可以直接执行 kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608快速排查清单
检查项 命令 Kafka 是否安装 ls /opt/module/kafka/bin/当前在哪个目录 pwdKafka 进程是否运行 `jps 端口是否监听 `netstat -tlnp 最常见的情况就是没有进入 Kafka 根目录,切换到正确目录即可解决。
进入 Kafka 根目录,执行 bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608 没反应?
执行
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608后没反应 (光标停住、没有报错、也没有输出),这其实是正常现象,说明消费者已经成功启动,正在等待数据。
为什么没反应?
Kafka 消费者启动后,会持续监听 指定的 Topic(
a2608),等待新消息到来。此时:
没有输出 = 还没有收到消息
光标闪烁 = 程序在运行,处于阻塞等待状态
不要按 Ctrl+C 退出
4. 启动 Flume 作业
bash
cd $FLUME_HOME
bin/flume-ng agent -c conf -n a1 -f job/flume-kafka.conf -Dflume.root.logger=INFO,console
5. 模拟日志数据写入
bash
echo 111 >> /opt/module/flume/data/flume.log
echo 222 >> /opt/module/flume/data/flume.log
echo 333 >> /opt/module/flume/data/flume.log
echo 444 >> /opt/module/flume/data/flume.log
6. 验证
- Kafka 消费者窗口应能实时输出写入的日志内容
八、总结图示
text
日志文件 → Flume(Source → Channel → Kafka Sink)→ Kafka(Topic)→ Kafka 消费者
-
Flume 作为生产者将数据写入 Kafka
-
Kafka 作为消息队列存储数据
-
消费者从 Kafka 实时拉取数据
重新梳理一下具体的操作:按照Kafka生产者、Kafka消费者、Flume来区分,各自都需要什么样的操作,顺序是什么?我是初学者,从Linux环境开始,给出具体的操作,标注操作顺序。是需要打开3个窗口吗?
好的,我来为你完整梳理一遍操作流程,从零开始,按顺序执行,清清楚楚。
总体概览
你需要打开 3 个终端窗口(都连到同一台 Linux 服务器):
| 窗口 | 角色 | 作用 |
|---|---|---|
| 窗口1 | Flume | 监控日志文件,发送数据到 Kafka |
| 窗口2 | Kafka 消费者 | 等待并显示从 Kafka 收到的消息 |
| 窗口3 | 模拟日志生产 | 向日志文件写入内容 |
数据流向:
窗口3: echo >> flume.log → 窗口1: Flume 监控到变化 → 窗口1: Flume 发送到 Kafka → 窗口2: Kafka 消费者显示消息
实际开了5个窗口(窗口重命名更清晰)

前置条件(先确认一下)
在开始之前,确保以下服务已启动:
bash
# 在任意窗口执行
jps
# 应该看到类似输出:
# 12345 QuorumPeerMain (ZooKeeper)
# 12346 Kafka (Kafka)
如果没有启动,先执行:
bash
# 启动 ZooKeeper
cd /opt/module/zookeeper # 替换成你的 ZooKeeper 路径
bin/zkServer.sh start
# 启动 Kafka
cd /opt/module/kafka # 替换成你的 Kafka 路径
bin/kafka-server-start.sh -daemon config/server.properties
操作顺序(按步骤执行)
第一步:创建 Topic(只需执行一次)
在任意窗口执行:
bash
bash
cd /opt/module/kafka
bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --topic a2608 --partitions 1 --replication-factor 1
验证 Topic 创建成功:
bash
bin/kafka-topics.sh --bootstrap-server localhost:9092 --list
# 应该能看到 a2608
第二步:打开 3 个终端窗口
-
窗口1:Flume
-
窗口2:Kafka 消费者
-
窗口3:模拟日志
第三步:窗口2 - 启动 Kafka 消费者(等待数据)
bash
cd /opt/module/kafka
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608
现象:光标停住不动,没有输出 → ✅ 正常,正在等待数据。
⚠️ 这个窗口保持运行,不要按 Ctrl+C。
第四步:窗口1 - 启动 Flume(监控日志文件)
4.1 先准备好日志文件目录
bash
mkdir -p /opt/module/flume/data/
touch /opt/module/flume/data/flume.log
4.2 创建 Flume 配置文件
bash
mkdir -p /opt/module/flume/job/
vim /opt/module/flume/job/flume-kafka.conf
将以下内容粘贴进去:
properties
bash
# define
a1.sources = r1
a1.sinks = k1
a1.channels = c1
# source - 监控日志文件
a1.sources.r1.type = exec
a1.sources.r1.command = tail -f /opt/module/flume/data/flume.log
# sink - 发送到 Kafka
a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
a1.sinks.k1.kafka.bootstrap.servers = localhost:9092
a1.sinks.k1.kafka.topic = a2608
a1.sinks.k1.kafka.flumeBatchSize = 20
a1.sinks.k1.kafka.producer.acks = 1
a1.sinks.k1.kafka.producer.linger.ms = 1
# channel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
# bind
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
4.3 启动 Flume
bash
cd /opt/module/flume
bin/flume-ng agent -c conf -n a1 -f job/flume-kafka.conf -Dflume.root.logger=INFO,console
现象:会看到一堆启动日志,最后类似:
bash
INFO source.ExecSource: Command 'tail -f /opt/module/flume/data/flume.log' started
⚠️ 这个窗口保持运行,不要按 Ctrl+C。
第五步:窗口3 - 模拟写入日志数据
bash
# 向日志文件写入内容
echo "Hello Kafka" >> /opt/module/flume/data/flume.log
echo "This is test message 1" >> /opt/module/flume/data/flume.log
echo "This is test message 2" >> /opt/module/flume/data/flume.log
模拟写入日志数据没反应,不需要进入什么环境吗
bashLast login: Mon Jun 1 17:50:00 2026 from 192.168.5.1 [hadoop@node100 ~]$ echo "Hello Kafka" >> /opt/module/flume/data/flume.log [hadoop@node100 ~]$ echo "This is test message 1" >> /opt/module/flume/data/flume.log [hadoop@node100 ~]$ echo "This is test message 2" >> /opt/module/flume/data/flume.log [hadoop@node100 ~]$
不需要进入任何特殊环境 !你直接在 Linux 命令行执行
echo命令就是正确的。
第六步:观察结果
窗口2(Kafka 消费者) 应该会立即显示:
bash
Hello Kafka
This is test message 1
This is test message 2
窗口1(Flume) 会显示发送成功的日志。
你的配置文件中 Topic 名称是
one,但你的消费者监听的是a2608。
问题所在
组件 Topic Flume 配置 oneKafka 消费者 a2608两者不一致,所以消费者收不到消息!
修改 Flume 配置,把 Topic 改为
a2608。
bashsed -i 's/one/a2608/g' /opt/module/flume/job/flume-kafka.conf # 验证修改结果 cat /opt/module/flume/job/flume-kafka.conf | grep topic
推荐统一使用 a2608
执行以下完整步骤:
步骤1:修改 Flume 配置
bashsed -i 's/one/a2608/g' /opt/module/flume/job/flume-kafka.conf # 验证 grep "topic" /opt/module/flume/job/flume-kafka.conf # 应该输出:a1.sinks.k1.kafka.topic = a2608步骤2:停止 Flume
在窗口1按
Ctrl+C步骤3:清空日志文件并写入新数据
bash# 窗口3执行 > /opt/module/flume/data/flume.log echo "Test message 1" >> /opt/module/flume/data/flume.log echo "Test message 2" >> /opt/module/flume/data/flume.log步骤4:启动消费者(窗口2)
bashcd $KAFKA_HOME bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608步骤5:启动 Flume(窗口1)
bashcd /opt/module/flume bin/flume-ng agent -c conf -n a1 -f job/flume-kafka.conf -Dflume.root.logger=INFO,console步骤6:写入新数据触发发送(窗口3)
bashecho "Trigger new data" >> /opt/module/flume/data/flume.log步骤7:观察窗口2
应该立即显示
Trigger new data
另外注意:配置文件中的 Kafka 地址
你的配置使用的是
node100:9092,而消费者使用的是localhost:9092。如果
node100就是当前机器(hostname 为 node100),那么没问题。
但为了确保一致,建议都改成
localhost:9092:
bashsed -i 's/node100/localhost/g' /opt/module/flume/job/flume-kafka.conf # 验证 grep "bootstrap.servers" /opt/module/flume/job/flume-kafka.conf # 应该输出:a1.sinks.k1.kafka.bootstrap.servers = localhost:9092
验证修复是否成功
执行完上述步骤后,在窗口3执行:
bashecho "Final test" >> /opt/module/flume/data/flume.log窗口2 应该立即显示
Final test✅
完整流程图
bash
┌─────────────────────────────────────────────────────────────────┐
│ Linux 服务器 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 窗口3 窗口1 窗口2 │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ echo │ ──写入──→ │ flume.log │ │ │ │
│ │ 写入 │ │ │ │ Kafka │ │
│ │ 日志 │ └───┬────┘ │ 消费者 │ │
│ └────────┘ │ │ │ │
│ │ tail -f 监控 │ 显示 │ │
│ ▼ │ 消息 │ │
│ ┌────────┐ │ │ │
│ │ Flume │ ──发送──→ │ Kafka │ │
│ │ Agent │ 数据 │ Topic │ │
│ └────────┘ │ a2608 │ │
│ └───┬────┘ │
│ │ │
│ │ 消费 │
│ ▼ │
│ ┌────────┐ │
│ │ 窗口2 │ │
│ │ 显示 │ │
│ └────────┘ │
└─────────────────────────────────────────────────────────────────┘
常见问题速查
| 问题 | 原因 | 解决方法 |
|---|---|---|
消费者启动报错 Connection refused |
Kafka 没启动 | 启动 Kafka |
消费者启动报错 No such file or directory |
不在 Kafka 根目录 | cd /opt/module/kafka |
| 消费者启动后没反应 | ✅ 正常等待数据 | 去窗口3写数据 |
| Flume 启动报错 | 配置文件有问题 | 检查配置文件路径和内容 |
| 消费者收不到消息 | Topic 名称不一致 | 检查 Flume 和消费者中的 topic 名都是 a2608 |
| 消费者收不到消息 | Kafka 和 Flume 的 bootstrap.servers 不一致 | 都使用 localhost:9092 |
快速复盘(命令速查表)
| 步骤 | 窗口 | 命令 |
|---|---|---|
| 创建 Topic | 任意 | cd /opt/module/kafka && bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --topic a2608 --partitions 1 --replication-factor 1 |
| 启动消费者 | 窗口2 | cd /opt/module/kafka && bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608 |
| 创建日志文件 | 窗口1 | mkdir -p /opt/module/flume/data && touch /opt/module/flume/data/flume.log |
| 启动 Flume | 窗口1 | cd /opt/module/flume && bin/flume-ng agent -c conf -n a1 -f job/flume-kafka.conf -Dflume.root.logger=INFO,console |
| 写入测试数据 | 窗口3 | echo "test" >> /opt/module/flume/data/flume.log |
创建 Flume 配置文件这一步,vim进去后卡住了,按i也没有进入编辑状态
这种情况通常是 vim 没有正常启动 或者终端卡住了。教你几种解决方法:
原因分析
最可能的原因是你在 vim 里不小心按了 Ctrl+S(冻结屏幕),或者 vim 启动时出现了问题。
解决方法
方法1:解除终端冻结(最快)
如果你不小心按了
Ctrl+S,终端会被冻结。按一下
Ctrl+Q即可解除冻结。
Ctrl+S= 冻结屏幕
Ctrl+Q= 解除冻结解除后应该能看到 vim 界面,再按
i进入编辑模式。
方法2:强制退出 vim 重新进入
如果按
Ctrl+Q没用,按以下步骤强制退出:bash
# 按 Esc 键(确保退出编辑模式) # 然后输入以下命令强制退出 :q! # 按回车如果完全卡死,可以:
bash
# 在另一个终端窗口执行,杀掉 vim 进程 pkill -9 vim然后重新进入:
bash
vim /opt/module/flume/job/flume-kafka.conf
方法3:使用 nano(更简单的编辑器)
如果 vim 总是出问题,可以用
nano,对初学者更友好:bash
# 安装 nano(如果没有) yum install nano -y # CentOS/RHEL # 或 apt install nano -y # Ubuntu # 使用 nano 编辑 nano /opt/module/flume/job/flume-kafka.confnano 操作:
直接输入内容
Ctrl+O保存
Ctrl+X退出
方法4:使用 echo 直接写入文件(最简单)
不需要打开编辑器,直接用命令写入配置:
bash
# 先创建目录 mkdir -p /opt/module/flume/job/ # 用 cat 命令直接写入文件 cat > /opt/module/flume/job/flume-kafka.conf << 'EOF' # define a1.sources = r1 a1.sinks = k1 a1.channels = c1 # source a1.sources.r1.type = exec a1.sources.r1.command = tail -f /opt/module/flume/data/flume.log # sink a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink a1.sinks.k1.kafka.bootstrap.servers = localhost:9092 a1.sinks.k1.kafka.topic = a2608 a1.sinks.k1.kafka.flumeBatchSize = 20 a1.sinks.k1.kafka.producer.acks = 1 a1.sinks.k1.kafka.producer.linger.ms = 1 # channel a1.channels.c1.type = memory a1.channels.c1.capacity = 1000 a1.channels.c1.transactionCapacity = 100 # bind a1.sources.r1.channels = c1 a1.sinks.k1.channel = c1 EOF # 验证文件是否创建成功 cat /opt/module/flume/job/flume-kafka.conf这个方法最可靠,不会卡住。
方法5:检查终端是否正常
如果以上方法都不行,可能是终端会话本身出问题了:
bash
# 查看当前终端是否正常 echo "test" # 如果没反应,说明终端可能卡死,建议: # 1. 关闭当前终端窗口 # 2. 重新连接 Linux # 3. 重新开始操作
推荐的完整流程(避免踩坑)
bash
# 1. 创建目录 mkdir -p /opt/module/flume/job/ # 2. 用 cat 命令直接创建配置文件(不会卡住) cat > /opt/module/flume/job/flume-kafka.conf << 'EOF' a1.sources = r1 a1.sinks = k1 a1.channels = c1 a1.sources.r1.type = exec a1.sources.r1.command = tail -f /opt/module/flume/data/flume.log a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink a1.sinks.k1.kafka.bootstrap.servers = localhost:9092 a1.sinks.k1.kafka.topic = a2608 a1.sinks.k1.kafka.flumeBatchSize = 20 a1.sinks.k1.kafka.producer.acks = 1 a1.sinks.k1.kafka.producer.linger.ms = 1 a1.channels.c1.type = memory a1.channels.c1.capacity = 1000 a1.channels.c1.transactionCapacity = 100 a1.sources.r1.channels = c1 a1.sinks.k1.channel = c1 EOF # 3. 验证文件内容 cat /opt/module/flume/job/flume-kafka.conf
建议直接用方法4(cat 命令写入) ,最简单且不会出问题。
所有办法都不行,我是关闭了窗口,重新来的。
总结
方法 难度 推荐度 Ctrl+Q解除冻结⭐ ⭐⭐⭐⭐⭐(先试这个) :q!退出 vim⭐ ⭐⭐⭐⭐ 用 nano编辑⭐⭐ ⭐⭐⭐⭐ 用 cat直接写入⭐ ⭐⭐⭐⭐⭐(最推荐) 重启终端 ⭐ ⭐⭐⭐
窗口2 显示了 Final test,所以Flume是干嘛用的,好像没变化。
太好了!窗口2显示了 Final test,说明整个流程已经跑通了! 🎉
现在回答你的问题:Flume 是干嘛用的?好像没变化?
Flume 在这个流程中的作用
没有 Flume 的情况(你手动做的)
text
你手动执行 echo → 直接写入文件 → ? → Kafka 消费者看到消息
等等,这里有个问题:文件本身不会自动发送到 Kafka!
有 Flume 的情况(现在运行的)
text
你执行 echo → 写入文件 → Flume 监控文件变化 → Flume 发送到 Kafka → 消费者显示消息
Flume 扮演的角色:把"文件中的新数据"自动抓取并发送到 Kafka。
证明 Flume 在工作
你可以做个对比实验:
实验1:停止 Flume,写入数据
bash
# 窗口1 按 Ctrl+C 停止 Flume
# 窗口3 写入数据
echo "No Flume test" >> /opt/module/flume/data/flume.log
# 观察窗口2(消费者)→ 不会有任何显示 ❌
实验2:重新启动 Flume,写入数据
bash
# 窗口1 重新启动 Flume
cd /opt/module/flume
bin/flume-ng agent -c conf -n a1 -f job/flume-kafka.conf -Dflume.root.logger=INFO,console
# 窗口3 写入数据
echo "With Flume test" >> /opt/module/flume/data/flume.log
# 观察窗口2(消费者)→ 会显示 "With Flume test" ✅
这就是 Flume 的作用! 没有 Flume,文件中的新数据不会自动进入 Kafka。
整个数据流的完整解释
bash
┌─────────────────────────────────────────────────────────────────────┐
│ 数据流向 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ [你的操作] │
│ ↓ │
│ echo "test" >> flume.log │
│ ↓ │
│ [Linux 文件] │
│ /opt/module/flume/data/flume.log │
│ ↓ │
│ [Flume] ← tail -f 监控文件,发现新内容 │
│ ↓ │
│ Flume 读取新内容,封装成消息 │
│ ↓ │
│ Flume 通过 KafkaSink 发送到 Kafka │
│ ↓ │
│ [Kafka] Topic: a2608 │
│ ↓ │
│ [Kafka 消费者] 拉取消息 │
│ ↓ │
│ [窗口2] 显示消息 │
│ │
└─────────────────────────────────────────────────────────────────────┘
为什么你觉得"没变化"?
因为你现在 Flume 一直在运行,所以每次写入文件,Flume 自动帮你发送了。这正是 Flume 的价值所在:
| 场景 | 你需要做的 | Flume 做的 |
|---|---|---|
| 没有 Flume | 写文件 + 手动写代码/命令发送到 Kafka | 无 |
| 有 Flume | 只写文件 | 自动监控 + 自动发送 |
Flume 的典型应用场景
-
日志收集:服务器上的日志文件 → Flume 监控 → 发送到 Kafka → 供 Spark/Flink 实时分析
-
数据集成:多个数据源(文件、网络端口、HTTP)→ Flume 统一收集 → 发送到 Kafka
-
解耦:数据生产方只需要写文件,不需要知道 Kafka 的存在
你现在可以做的额外验证
1. 查看 Flume 的发送日志
在 Flume 窗口(窗口1),你应该能看到类似这样的日志:
text
INFO kafka.KafkaSink: Sending message to Kafka: Final test
这证明 Flume 确实在发送消息。
2. 确认没有 Flume 时不会自动发送
bash
# 停止 Flume(窗口1按 Ctrl+C)
# 写入数据
echo "Flume stopped test" >> /opt/module/flume/data/flume.log
# 观察窗口2 → 不会有消息
# 重启 Flume
# 写入新数据
echo "Flume restarted test" >> /opt/module/flume/data/flume.log
# 观察窗口2 → 会显示
总结
| 组件 | 职责 | 你的感受 |
|---|---|---|
| 你的 echo 命令 | 产生数据(模拟日志) | 主动操作 |
| Flume | 监控文件,自动发送到 Kafka | 自动化工具,透明工作 |
| Kafka | 消息队列,暂存数据 | 中间件 |
| 消费者 | 显示收到的数据 | 被动接收 |
Flume 让你省去了"手动把文件内容发送到 Kafka"这一步。你只管往文件里写数据,Flume 自动帮你送到 Kafka。
这就是它看起来"没变化"但实际很重要的原因------它让数据流转自动化了!
老师的课堂笔记中,第一个示例,没有使用flume,好像也能通信。
往队列中发送消息:
--a窗口 bin/kafka-console-producer.sh --broker-list localhost:9092 --topic a2608 消费指定队列中的消息:
--b窗口 bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608
你说得完全正确!Kafka 本身就可以直接通信,不需要 Flume。
让我帮你理清这两者的区别,以及为什么课堂笔记中要引入 Flume。
Kafka 直接通信(笔记中第一个示例)
操作方式
| 窗口 | 角色 | 命令 |
|---|---|---|
| 窗口A | 生产者 | bin/kafka-console-producer.sh --broker-list localhost:9092 --topic a2608 |
| 窗口B | 消费者 | bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608 |
数据流向
text
窗口A(生产者)→ 直接发送 → Kafka → 窗口B(消费者)显示
特点:
-
手动输入消息,手动发送
-
没有中间环节
-
适合测试和调试
引入 Flume 的场景(笔记中第二个示例)
为什么需要 Flume?
在实际生产环境中,数据来源不是手动输入的,而是来自:
-
应用程序日志文件(不断增长)
-
数据库变更日志
-
传感器数据
-
网站访问日志
-
...
Flume 的作用:自动监控这些数据源,并把数据发送到 Kafka。
数据流向
text
日志文件(自动增长)→ Flume(自动监控)→ Kafka → 消费者
特点:
-
自动化,不需要手动输入
-
适合生产环境的数据采集
对比总结
| 对比项 | Kafka 直接通信 | Flume + Kafka |
|---|---|---|
| 数据来源 | 手动输入 | 日志文件/数据源 |
| 是否需要人工 | 每次都要手动输入 | 自动采集 |
| 适用场景 | 测试、调试 | 生产环境日志采集 |
| 复杂度 | 简单 | 稍复杂 |
两者的关系图
方式1:Kafka 直接通信(手动)
text
[你打字] → [Kafka生产者] → [Kafka] → [消费者] → [显示]
方式2:Flume + Kafka(自动)
text
[日志文件] → [Flume监控] → [Kafka] → [消费者] → [显示]
↑
echo 写入
实际生产场景举例
场景:监控网站访问日志
没有 Flume:
bash
# 你需要一直手动执行
cat access.log | kafka-console-producer ...
# 或者写一个定时脚本
有 Flume:
bash
# Flume 配置文件写一次,永久生效
# 日志每产生一行,Flume 自动发送到 Kafka
# 你什么都不用做
课堂笔记的安排逻辑
-
第一个示例:让你理解 Kafka 基本的生产-消费模型
-
第二个示例:告诉你实际工作中如何用 Flume 自动化采集数据
Flume 的价值:当你有一个持续产生数据的文件(比如应用程序日志),你不可能每次都手动输入。Flume 帮你自动化这个过程。
你现在已经掌握的技能
✅ Kafka 基本命令(创建 topic、生产、消费)
✅ Flume 配置(source、channel、sink)
✅ Flume 监控文件并发送到 Kafka
✅ 整个数据管道:文件 → Flume → Kafka → 消费者
下一步可以学什么
-
Flume 其他 Source:监控目录、监听网络端口、读取 HTTP 数据
-
Kafka 消费者组:多个消费者协同消费
-
Kafka 分区:提高并发处理能力
简单记忆:
-
Kafka 直接通信 = 手动挡汽车(控制感强)
-
Flume + Kafka = 自动驾驶(省心,自动化)
两者各有用途,你现在都学会了!
你前面说的部分没看懂,这里:配置文件中的 Kafka 地址 你的配置使用的是 node100:9092,而消费者使用的是 localhost:9092。 如果 node100 就是当前机器(hostname 为 node100),那么没问题。
问题的本质
localhost 和 node100 是两个不同的地址写法,它们可能指向同一台机器,也可能指向不同的机器。
| 地址 | 含义 | 实际解析 |
|---|---|---|
localhost |
本机 | 永远指向 127.0.0.1(当前这台机器自己) |
node100 |
主机名 | 取决于 /etc/hosts 或 DNS 的配置 |
在你的环境中
你的机器主机名是 node100(从提示符 [hadoop@node100 ~]$ 可以看出)。
情况A:localhost 和 node100 指向同一台机器
如果 /etc/hosts 文件中有这样的配置:
bash
cat /etc/hosts
输出:
text
127.0.0.1 localhost localhost.localdomain
192.168.x.x node100
那么:
-
localhost→ 127.0.0.1(本机环回地址) -
node100→ 192.168.x.x(本机的实际IP)
虽然指向同一台物理机器,但 Kafka 可能会认为它们是不同的地址,这取决于 Kafka 的配置。
为什么建议统一使用 localhost
1. 避免配置不一致导致的问题
bash
# Flume 使用 node100:9092
a1.sinks.k1.kafka.bootstrap.servers = node100:9092
# 消费者使用 localhost:9092
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 ...
潜在问题 :如果 Kafka 配置的 advertised.listeners 只绑定了 localhost,那么 Flume 用 node100 连接可能会失败。
2. 你的实际情况
从你的日志来看,Flume 成功连接到了 Kafka (显示了 Cluster ID),所以你的环境中 node100:9092 和 localhost:9092 都能正常工作。
正确的理解
| 说法 | 是否正确 | 说明 |
|---|---|---|
node100 和 localhost 指向同一台机器 |
✅ 正确 | 因为你在 node100 上执行命令 |
| 可以混用 | ⚠️ 不一定 | 取决于 Kafka 的监听配置 |
| 建议统一 | ✅ 正确 | 避免不必要的麻烦 |
检查你的 Kafka 监听配置
bash
bash
# 查看 Kafka 配置
cat $KAFKA_HOME/config/server.properties | grep listeners
可能的输出:
text
# 情况1:只监听了 localhost
listeners=PLAINTEXT://localhost:9092
# 情况2:监听了所有地址
listeners=PLAINTEXT://0.0.0.0:9092
# 情况3:监听了 node100
listeners=PLAINTEXT://node100:9092
-
情况1 :只能用
localhost连接 -
情况2 :
localhost和node100都可以 -
情况3 :只能用
node100连接
最简单的原则
在同一个实验环境中,所有组件使用相同的地址:
bash
# Flume 配置
a1.sinks.k1.kafka.bootstrap.servers = localhost:9092
# Kafka 消费者
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 ...
# Kafka 生产者
bin/kafka-console-producer.sh --broker-list localhost:9092 ...
全部统一用 localhost,就不会有歧义。
总结
| 你的问题 | 答案 |
|---|---|
node100 是当前机器吗? |
是的 |
可以用 node100 吗? |
可以(你的环境能用) |
| 建议用哪个? | localhost(更保险,更统一) |
| 为什么之前强调? | 因为很多同学混用后会连接失败 |
在你的环境中,两者都能工作,所以之前的问题(消费者收不到消息)真正的原因是 Topic 名称不一致 (one vs a2608),而不是地址问题。
Kafka 配置
bash
[hadoop@node100 ~]$ cat $KAFKA_HOME/config/server.properties | grep listeners
# listeners = listener_name://host_name:port
# listeners = PLAINTEXT://your.host.name:9092
#listeners=PLAINTEXT://:9092
# it uses the value for "listeners" if configured. Otherwise, it will use the value
#advertised.listeners=PLAINTEXT://your.host.name:9092
[hadoop@node100 ~]$
你的 Kafka 配置显示:
properties
#listeners=PLAINTEXT://:9092
这行被注释掉了 (前面有 #)。
这意味着什么?
当 listeners 被注释掉时,Kafka 使用默认配置 :PLAINTEXT://:9092(监听所有网络接口)。
默认配置的效果
| 连接方式 | 是否可用 | 原因 |
|---|---|---|
localhost:9092 |
✅ 可用 | 本机环回地址 |
127.0.0.1:9092 |
✅ 可用 | 本机IP |
node100:9092 |
✅ 可用 | 主机名解析到本机IP |
结论 :你的环境中,localhost 和 node100 都可以正常连接 Kafka。
为什么两种写法都能用?
Kafka 监听的是 0.0.0.0(所有网络接口):
text
bash
┌─────────────────────────────────────────────────────┐
│ 你的机器 node100 │
│ │
│ ┌─────────────┐ │
│ │ localhost │ ← 127.0.0.1 (环回地址) │
│ │ 127.0.0.1 │ │
│ └─────────────┘ │
│ │
│ ┌─────────────┐ │
│ │ node100 │ ← 192.168.x.x (实际IP) │
│ │ 192.168.x.x│ │
│ └─────────────┘ │
│ │
│ ↓ 都指向同一台机器 ↓ │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Kafka (监听 0.0.0.0:9092) │ │
│ │ 接受所有网络接口的连接 │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
总结你之前的成功
你最终成功时:
-
Flume 配置:
node100:9092✅ -
消费者配置:
localhost:9092✅
两者都能工作,因为它们最终都连接到了同一个 Kafka 实例。
实际建议
虽然两者都能用,但为了配置的统一和可移植性,建议:
properties
# Flume 配置
a1.sinks.k1.kafka.bootstrap.servers = localhost:9092
原因:
-
localhost在任何机器上都指向本机 -
配置文件复制到其他机器不用修改
-
更清晰地表达"Kafka 和 Flume 在同一台机器"
你的 Kafka 配置说明
| 配置项 | 你的状态 | 效果 |
|---|---|---|
listeners |
注释掉(使用默认) | 监听所有网络接口 |
advertised.listeners |
注释掉 | 使用 listeners 的值 |
这是最简单、最灵活的配置方式,适合学习环境。
现在一切清楚了吗?你的环境配置是正确的,之前的 Topic 名称不匹配是唯一的问题。恭喜你成功跑通了整个流程!🎉
本机环回地址是什么意思
本机环回地址(Loopback Address)
简单理解 :就是指向自己这台电脑的IP地址。
最常见的环回地址
| 地址 | 格式 | 说明 |
|---|---|---|
127.0.0.1 |
IPv4 | 最常用的环回地址 |
::1 |
IPv6 | IPv6版本的环回地址 |
localhost |
域名 | 自动解析到 127.0.0.1 |
通俗比喻
想象你的电脑是一个带信箱的房子:
| 地址类型 | 比喻 | 说明 |
|---|---|---|
192.168.1.100(实际IP) |
房子的门牌号 | 别人通过这个地址找到你 |
127.0.0.1(环回地址) |
房子内部的传话管道 | 你自己跟自己通信 |
环回地址就像你对自己说话:不需要出门,不需要经过邻居,直接传递信息。
实际效果
bash
# 这两种方式都会连接到你自己这台机器的 Kafka
ping 127.0.0.1 # 数据包不经过网卡,直接在系统内部转发
ping localhost # 解析成 127.0.0.1
ping node100 # 实际IP,数据包会经过网卡
图示理解
text
bash
┌─────────────────────────────────────────────────┐
│ 你的电脑 │
│ │
│ 应用程序A ──→ 127.0.0.1:9092 ──→ 应用程序B │
│ (环回地址) │
│ ⬆ 内部直接传递 │
│ ⬆ 不经过网卡 │
│ ⬆ 速度非常快 │
│ │
│ 应用程序A ──→ 192.168.1.100:9092 ──→ 应用程序B │
│ (实际IP) │
│ ⬆ 数据先发出网卡 │
│ ⬆ 再绕回来接收 │
│ ⬆ 相对慢一些 │
│ │
└─────────────────────────────────────────────────┘
为什么需要环回地址?
| 场景 | 说明 |
|---|---|
| 本地测试 | 开发时不需要实际网络,直接测试程序 |
| 服务通信 | 电脑上多个服务互相访问(如 Kafka → ZooKeeper) |
| 速度更快 | 不经过网卡,纯内存操作 |
| 不受网络影响 | 网线拔了也能用 |
在你的 Kafka 实验中
bash
# 消费者使用 localhost:9092
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic a2608
效果:
-
Kafka 客户端程序通过
127.0.0.1连接 -
数据不经过网卡
-
直接在系统内部传递
-
速度和稳定性最好
验证环回地址
bash
# 查看 localhost 解析成什么
ping -c 1 localhost
# 输出:PING localhost (127.0.0.1) ...
# 查看所有网络接口
ifconfig lo
# lo 就是环回接口(loopback)
# 通常显示:inet 127.0.0.1
总结
| 概念 | 一句话解释 |
|---|---|
| 环回地址 | 指向你自己的IP地址 |
| 127.0.0.1 | 最常用的环回地址 |
| localhost | 127.0.0.1 的域名别名 |
| 用途 | 本机内部通信,不需要真实网络 |
记忆口诀:环回环回,掉头就回,不往外跑,自己和自己开会。
你的配置文件中 Topic 名称是 one,但你的消费者监听的是 a2608。详细解释一下配置文件中各行的作用,因为不熟悉,所以最开始看不出来错误在哪。
非常好的问题!学习新框架时,不理解配置的含义是最大的障碍。我来逐行解释 Flume 配置文件,并说明为什么 Topic 不匹配会出问题。
Flume 配置文件完整解析
配置文件结构
Flume 配置由三大部分组成:Source(来源) 、Channel(通道) 、Sink(去向)
text
数据流向:Source → Channel → Sink
第一部分:定义组件名称
properties
# define
a1.sources = r1
a1.sinks = k1
a1.channels = c1
| 配置项 | 含义 | 说明 |
|---|---|---|
a1 |
Agent 名称 | Flume 进程的名称,可以任意起名 |
sources |
数据来源组件 | 定义有哪些数据源(可以有多个) |
r1 |
Source 名称 | 给这个数据源起个名字,可以任意起名 |
sinks |
数据去向组件 | 定义数据要发送到哪里(可以有多个) |
k1 |
Sink 名称 | 给这个数据去向起个名字 |
channels |
通道组件 | 定义 Source 和 Sink 之间的缓冲区 |
c1 |
Channel 名称 | 给这个通道起个名字 |
通俗理解:
我有一个叫
a1的 Flume 进程,它从r1读取数据,通过c1通道,发送到k1。
第二部分:配置 Source(数据来源)
properties
# source
a1.sources.r1.type = exec
a1.sources.r1.command = tail -f /opt/module/flume/data/flume.log
| 配置项 | 值 | 含义 |
|---|---|---|
a1.sources.r1.type |
exec |
Source 类型是"执行Linux命令" |
a1.sources.r1.command |
tail -f /opt/module/flume/data/flume.log |
执行的命令是监控这个文件的变化 |
通俗理解:
执行
tail -f命令,持续监控/opt/module/flume/data/flume.log这个文件,文件有新内容就读取出来。
其他可能的 Source 类型:
-
spooldir:监控整个目录,有新文件就读取 -
netcat:监听网络端口 -
http:接收 HTTP 请求
第三部分:配置 Sink(数据去向)
properties
# sink
a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
a1.sinks.k1.kafka.bootstrap.servers = node100:9092
a1.sinks.k1.kafka.topic = one
a1.sinks.k1.kafka.flumeBatchSize = 20
a1.sinks.k1.kafka.producer.acks = 1
a1.sinks.k1.kafka.producer.linger.ms = 1
| 配置项 | 值 | 含义 |
|---|---|---|
a1.sinks.k1.type |
org.apache.flume.sink.kafka.KafkaSink |
Sink 类型是 Kafka(数据发送到 Kafka) |
a1.sinks.k1.kafka.bootstrap.servers |
node100:9092 |
Kafka 服务器地址(告诉 Flume Kafka 在哪) |
a1.sinks.k1.kafka.topic |
one |
发送到 Kafka 的哪个 Topic ⚠️ 这里是关键! |
a1.sinks.k1.kafka.flumeBatchSize |
20 |
每次批量发送多少条消息 |
a1.sinks.k1.kafka.producer.acks |
1 |
消息确认级别(1 = 等待 Leader 确认) |
a1.sinks.k1.kafka.producer.linger.ms |
1 |
发送前等待更多消息的时间(毫秒) |
通俗理解:
把数据发送到
node100这台机器的 Kafka,放进名叫one的 Topic 里。
第四部分:配置 Channel(通道/缓冲区)
properties
# channel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
| 配置项 | 值 | 含义 |
|---|---|---|
a1.channels.c1.type |
memory |
Channel 类型是"内存"(数据暂存在内存中) |
a1.channels.c1.capacity |
1000 |
通道最大能存储多少条消息 |
a1.channels.c1.transactionCapacity |
100 |
每次事务最多处理多少条消息 |
通俗理解:
在 Source 和 Sink 之间放一个临时仓库,Source 读取的数据先放这里,Sink 从这里取走发送。容量 1000 条,每次最多处理 100 条。
第五部分:绑定组件(组装起来)
properties
# bind
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
| 配置项 | 含义 |
|---|---|
a1.sources.r1.channels = c1 |
Source r1 把数据发到 Channel c1 |
a1.sinks.k1.channel = c1 |
Sink k1 从 Channel c1 取数据 |
通俗理解:
把 Source、Channel、Sink 连接起来,形成完整的数据流。
为什么 Topic 不匹配会导致收不到消息?
数据流向图
text
bash
┌─────────────────────────────────────────────────────────────────────┐
│ 你的 Flume 配置 │
│ │
│ flume.log ──→ [Source] ──→ [Channel] ──→ [Sink] │
│ │ │ │
│ │ ↓ │
│ │ 发送到 Kafka │
│ │ Topic = "one" ←─── ⚠️ 关键 │
│ │ │
└────────────────────│────────────────────────────────────────────────┘
│
↓
┌─────────────┐
│ Kafka │
│ Topic: one │ ← Flume 把数据发到这里
└─────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ 你的消费者命令 │
│ │
│ bin/kafka-console-consumer.sh --topic a2608 │
│ ↑ │
│ ⚠️ 从 Topic "a2608" 读 │
│ │
│ Kafka 收到消费请求:从 "a2608" 读数据 │
│ 但数据都在 "one" 里 → 没有数据 → 什么都不显示 │
└─────────────────────────────────────────────────────────────────────┘
类比理解
把 Kafka 想象成一个停车场:
| 概念 | 类比 |
|---|---|
| Topic | 停车场里的不同区域(A区、B区、C区) |
| Flume | 一辆送客的车 |
| 消费者 | 一辆接客的车 |
你的配置:
-
Flume(送客车)把客人送到 "one" 区
-
消费者(接客车)去 "a2608" 区 接客人
结果:接客车永远接不到人 ❌
修复后:
-
Flume 把客人送到 "a2608" 区
-
消费者也去 "a2608" 区 接人
结果:成功接到人 ✅
如何快速发现这种错误?
1. 查看 Flume 启动日志
**Flume 启动时会显示配置信息,但没有直接显示 Topic 名称。**不过你可以:
bash
# 查看 Flume 完整配置
cat /opt/module/flume/job/flume-kafka.conf | grep topic
2. 查看 Kafka 中的 Topic 列表
bash
cd $KAFKA_HOME
bin/kafka-topics.sh --bootstrap-server localhost:9092 --list
这会显示所有存在的 Topic。你可能会发现:
-
one(Flume 发送的) -
a2608(消费者监听的)
两个都存在,但数据只在一个里面。
3. 消费时加 --from-beginning
bash
# 尝试消费 one
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic one --from-beginning
# 如果看到你的测试消息,说明 Flume 工作正常,只是 Topic 不对
配置文件模板(带注释)
properties
bash
# ========== 1. 定义组件名称 ==========
# Agent名称.sources = Source名称
a1.sources = r1
# Agent名称.sinks = Sink名称
a1.sinks = k1
# Agent名称.channels = Channel名称
a1.channels = c1
# ========== 2. 配置Source ==========
# Source类型:exec = 执行Linux命令
a1.sources.r1.type = exec
# Source执行的命令:监控文件新增内容
a1.sources.r1.command = tail -f /opt/module/flume/data/flume.log
# ========== 3. 配置Sink ==========
# Sink类型:Kafka Sink
a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
# Kafka服务器地址(多个用逗号分隔)
a1.sinks.k1.kafka.bootstrap.servers = localhost:9092
# ⚠️ 重要:发送到Kafka的哪个Topic
a1.sinks.k1.kafka.topic = a2608
# 批量发送大小
a1.sinks.k1.kafka.flumeBatchSize = 20
# 消息确认级别
a1.sinks.k1.kafka.producer.acks = 1
# 延迟发送时间(毫秒)
a1.sinks.k1.kafka.producer.linger.ms = 1
# ========== 4. 配置Channel ==========
# Channel类型:内存
a1.channels.c1.type = memory
# 最大消息数量
a1.channels.c1.capacity = 1000
# 事务最大处理数
a1.channels.c1.transactionCapacity = 100
# ========== 5. 绑定组件 ==========
# Source绑定Channel
a1.sources.r1.channels = c1
# Sink绑定Channel
a1.sinks.k1.channel = c1
总结:你犯的错误和学到的经验
| 错误 | 原因 | 如何避免 |
|---|---|---|
Flume 用 Topic one,消费者用 a2608 |
配置文件中的 topic 参数被忽略 | 检查配置文件中的每个参数 |
经验教训:
-
配置文件中的每一行都有意义
-
排错时逐项检查每个参数是否匹配
-
用
grep快速查看关键配置 -
用
--list查看 Kafka 中实际存在的 Topic
现在你应该能看懂 Flume 配置了!有问题随时问。
还有一个疑问,最开始创建 Flume 配置文件这一步不是重复了很多次,但每次打开配置文件都还在。是教室环境,使用的统一安装的虚拟机环境,跟这个有关系吗,我想的是正常情况应该会提醒重复创建,或者打开配置文件是空白才对。以下命令执行了多次都没有报错 mkdir -p /opt/module/flume/data/ touch /opt/module/flume/data/flume.log mkdir -p /opt/module/flume/job/ 这个文件/opt/module/flume/job/flume-kafka.conf打开每次都有内容,我看不懂,所以就没有修改。好像是老师提前写好的。
为什么重复执行命令没有报错?
mkdir -p 不报错的原因
bash
mkdir -p /opt/module/flume/data/
| 情况 | mkdir -p 的行为 |
是否报错 |
|---|---|---|
| 目录不存在 | 创建目录 | ✅ 正常 |
| 目录已存在 | 什么都不做,直接返回成功 | ✅ 不报错 |
-p 参数的作用:
-
-p= parents(父目录) -
如果目录存在,静默跳过,不报错也不覆盖
-
所以执行多次完全没问题
没有 -p 的情况:
bash
mkdir /opt/module/flume/data/ # 第一次执行:成功
mkdir /opt/module/flume/data/ # 第二次执行:报错 "File exists"
touch 不报错的原因
bash
touch /opt/module/flume/data/flume.log
| 情况 | touch 的行为 |
是否报错 |
|---|---|---|
| 文件不存在 | 创建空文件 | ✅ 正常 |
| 文件已存在 | 更新文件的修改时间戳 | ✅ 不报错(不会清空内容) |
touch 不会覆盖或清空文件内容,只会更新时间戳。
为什么配置文件每次打开都有内容?
你猜对了!这是教室环境老师提前准备好的。
可能的情况
| 可能性 | 说明 |
|---|---|
| 老师预置的 | 老师为了教学方便,提前把配置写好了放在 /opt/module/flume/job/flume-kafka.conf |
| 共享虚拟机镜像 | 所有同学用的是同一个虚拟机镜像,文件本来就存在 |
| 之前的实验残留 | 这个教室环境可能被多次使用,文件一直保留着 |
验证文件是什么时候创建的
bash
# 查看文件的创建/修改时间
ls -l /opt/module/flume/job/flume-kafka.conf
# 输出示例:
# -rw-r--r-- 1 hadoop hadoop 1024 May 20 10:30 flume-kafka.conf
# ↑
# 这个时间是文件最后修改时间
如果时间比你上课时间还早,说明是老师提前放好的。
bash
# 查看文件内容中的注释
cat /opt/module/flume/job/flume-kafka.conf | head -5
如果有一些教学性质的注释(比如 # 这是Kafka Sink示例),更说明是老师准备的。
老师为什么提前放好配置文件?
| 原因 | 说明 |
|---|---|
| 节省时间 | 不需要每个同学从头敲配置,可以专注讲解 |
| 避免错误 | 防止同学敲错配置导致实验失败 |
| 统一环境 | 保证所有人的配置一致,方便教学 |
| 初学者友好 | 让你先跑通流程,之后再学配置细节 |
你应该怎么做?
1. 理解配置内容(你已经通过之前的学习做到了)
2. 修改配置来验证理解
bash
bash
# 先备份原配置
cp /opt/module/flume/job/flume-kafka.conf /opt/module/flume/job/flume-kafka.conf.bak
# 修改 topic 名称(你现在已经知道这个很重要了)
vim /opt/module/flume/job/flume-kafka.conf
# 或者用 sed 命令
sed -i 's/one/a2608/g' /opt/module/flume/job/flume-kafka.conf
3. 自己手写一个配置文件
bash
bash
# 创建你自己的配置文件
cat > /opt/module/flume/job/my-flume-kafka.conf << 'EOF'
a1.sources = r1
a1.sinks = k1
a1.channels = c1
a1.sources.r1.type = exec
a1.sources.r1.command = tail -f /opt/module/flume/data/flume.log
a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
a1.sinks.k1.kafka.bootstrap.servers = localhost:9092
a1.sinks.k1.kafka.topic = a2608
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
EOF
# 使用你自己的配置文件运行
bin/flume-ng agent -c conf -n a1 -f job/my-flume-kafka.conf -Dflume.root.logger=INFO,console
总结:你问的这个问题说明你学得很好
| 你的疑问 | 说明 |
|---|---|
| "命令执行多次没报错" | 你注意到了命令的幂等性(多次执行结果相同) |
| "文件每次打开都有内容" | 你发现了环境预置的事实 |
| "看不懂所以没修改" | 你谨慎对待不懂的内容,这是好习惯 |
现在你懂了配置的含义,就可以大胆修改了!
学习建议
作为初学者,这种教学环境的安排是合理的:
-
先跑通流程(用老师给的配置)→ 建立信心
-
再理解配置(我们刚才做的)→ 深入原理
-
最后自己写(课后练习)→ 真正掌握
你现在已经完成了第2步,可以进入第3步了!
就以上问答,重新总结Kafka课堂笔记,方便日后复习。