前言
在前几篇文章中我们主要介绍了datax,sqoop在大数据数据导入领域的应用场景。
datax与sqoop都是用于离线数据的导入,为了满足实时计算的需要,我们会用flume进行数据采集,今天就来介绍一下flume是如何采集数据到spark中用于流计算的。
以下是在 Linux 服务器端,使用 Flume 采集 Kafka 数据到 Spark Streaming 进行流式计算的全流程实操指南,包含环境搭建、配置细节、代码实现及验证步骤。
一、环境准备与组件安装
假设服务器环境为 CentOS 7,集群包含 3 个节点(node1:Kafka/ZooKeeper;node2:Flume;node3:Spark`)
各组件版本如下:
Kafka:2.8.1(依赖 ZooKeeper 3.6.3)
Flume:1.9.0
Spark:3.2.0(支持 Spark Streaming)
JDK:1.8.0_301
服务器划分如下:
node1(Kafka/ZooKeeper):192.168.1.10
node2(Flume):192.168.1.11
node3(Spark/PySpark):192.168.1.12
一、预先准备操作
1.1Kafka 安装(node1)
1.11下载并解压 Kafka:
cd /opt
wget https://downloads.apache.org/kafka/3.6.1/kafka_2.13-3.6.1.tgz
tar -zxvf kafka_2.13-3.6.1.tgz
mv kafka_2.13-3.6.1 kafka
1.12配置 server.properties(/usr/local/kafka/config/server.properties)
# 基础配置
broker.id=0
listeners=PLAINTEXT://node1:9092 # 监听地址(替换为 node1 IP)
log.dirs=/data/kafka-logs # 日志存储路径(需提前创建目录:mkdir -p /data/kafka-logs)
zookeeper.connect=node1:2181 # ZooKeeper 地址(Kafka 3.6+ 内置 ZooKeeper,无需额外安装)
1.13启动 Kafka
# 启动内置 ZooKeeper(Kafka 3.6+ 推荐使用 KRaft 模式,此处简化为内置 ZooKeeper)
/opt/kafka/bin/zookeeper-server-start.sh -daemon /opt/kafka/config/zookeeper.properties
# 启动 Kafka Broker
/opt/kafka/bin/kafka-server-start.sh -daemon /opt/kafka/config/server.properties
1.2Flume 安装(node2)
1.21下载并解压 Flume:
cd /opt
wget https://downloads.apache.org/flume/1.9.0/apache-flume-1.9.0-bin.tar.gz
tar -zxvf apache-flume-1.9.0-bin.tar.gz
mv apache-flume-1.9.0-bin flume
1.3PySpark 安装(node3)
1.31 安装 Spark(包含 PySpark)
cd /opt
wget https://downloads.apache.org/spark/spark-3.3.2/spark-3.3.2-bin-hadoop3.tgz
tar -zxvf spark-3.3.2-bin-hadoop3.tgz
mv spark-3.3.2-bin-hadoop3 spark
1.32 配置 PySpark(可选,若需本地开发)
# 安装 Python 3.8+(CentOS 7 默认是 2.7,需升级)
yum install -y python38
ln -sf /usr/bin/python3.8 /usr/bin/python3
# 安装 PySpark(版本与 Spark 一致)
pip3 install pyspark==3.3.2
二、代码编写
这里解释一下分为了flume端代码编写和pyspark端代码编写
2.1 flume端代码编写
配置 Flume(关键:Kafka Source → Memory Channel → Avro Sink)
在 /opt/flume/conf 目录下创建配置文件 kafka-to-spark.conf,内容如下(参数逐行解释):
# ------------------------------
# 1. Agent 基础信息(名称为 agent1)
# ------------------------------
agent1.sources = kafka_source
agent1.channels = memory_channel
agent1.sinks = avro_sink
# ------------------------------
# 2. Kafka Source(从 Kafka 消费数据)
# ------------------------------
agent1.sources.kafka_source.type = org.apache.flume.source.kafka.KafkaSource # Kafka Source 类型
agent1.sources.kafka_source.kafka.bootstrap.servers = node1:9092 # Kafka 集群地址(必须可访问)
agent1.sources.kafka_source.kafka.topics = hive_data_topic # 消费的主题(与 Kafka 主题一致)
agent1.sources.kafka_source.kafka.consumer.group.id = flume-consumer-group # 消费者组 ID(唯一标识 Flume 消费者)
agent1.sources.kafka_source.kafka.auto.offset.reset = latest # 从最新偏移量开始消费(避免重复消费历史数据)
agent1.sources.kafka_source.kafka.consumer.timeout.ms = 10000 # 消费者超时时间(超时后重新连接)
agent1.sources.kafka_source.batchSize = 1000 # 每次从 Kafka 拉取的事件数(根据数据量调整)
agent1.sources.kafka_source.kafka.consumer.request.timeout.ms = 30000 # 请求超时时间(防止网络波动)
# ------------------------------
# 3. Memory Channel(临时存储数据)
# ------------------------------
agent1.channels.memory_channel.type = memory # 内存 Channel(性能高但不可靠,生产建议用 File Channel)
agent1.channels.memory_channel.capacity = 10000 # Channel 最大存储事件数(根据内存大小调整,避免 OOM)
agent1.channels.memory_channel.transactionCapacity = 1000 # 单次事务处理的事件数(与 batchSize 匹配)
agent1.channels.memory_channel.keep-alive = 3 # 事务超时时间(秒)
# ------------------------------
# 4. Avro Sink(发送到 PySpark 的 Avro 端口)
# ------------------------------
agent1.sinks.avro_sink.type = avro # Avro Sink 类型(Flume 内置)
agent1.sinks.avro_sink.hostname = node3 # PySpark 所在节点的主机名/IP(必须可访问)
agent1.sinks.avro_sink.port = 41414 # PySpark 监听的端口(需与 PySpark 代码一致)
agent1.sinks.avro_sink.batch-size = 1000 # 每次向 Spark 发送的事件数(与 Channel 事务匹配)
agent1.sinks.avro_sink.threads = 2 # 发送线程数(提升并发)
# ------------------------------
# 5. 绑定组件(关键!)
# ------------------------------
agent1.sources.kafka_source.channels = memory_channel # Source 连接 Channel
agent1.sinks.avro_sink.channel = memory_channel # Sink 连接 Channel
2.2pyspark端代码编写
在 /root/spark-apps 目录下(需提前创建)创建 flume_kafka_streaming.py,
代码如下(逐行注释):
from pyspark import SparkConf
from pyspark.streaming import StreamingContext
from pyspark.streaming.flume import FlumeUtils
def main():
# ------------------------------
# 1. 配置 Spark 应用(必须与集群匹配)
# ------------------------------
conf = SparkConf() \
.setAppName("FlumeKafkaStreaming") \ # 应用名称(在 Spark UI 中显示)
.setMaster("spark://node3:7077") \ # Spark Master 地址(node3 的 IP:7077)
.set("spark.executor.memory", "2g") \ # 每个 Executor 的内存(根据集群资源调整)
.set("spark.executor.cores", "2") \ # 每个 Executor 的核心数
.set("spark.default.parallelism", "3") # 并行度(建议等于 Kafka 分区数 3)
ssc = StreamingContext(conf, 5) # 批处理间隔 5 秒(根据延迟需求调整)
# ------------------------------
# 2. 监听 Flume 的 Avro 端口(关键!)
# ------------------------------
# 参数说明:ssc(StreamingContext)、Spark 节点 IP/主机名、监听端口(与 Flume 的 avro_sink.port 一致)
flume_stream = FlumeUtils.createStream(
ssc,
"node3", # Spark 自身 IP(需与 Flume 的 avro_sink.hostname 一致)
41414 # 监听端口(必须与 Flume 的 avro_sink.port 一致)
)
# ------------------------------
# 3. 数据处理逻辑(示例:词频统计)
# ------------------------------
# Flume 事件的 body 是字节数组,需解码为字符串(UTF-8 编码)
processed_stream = flume_stream \
.map(lambda event: event.body.decode("utf-8")) \ # 解码字节数组为字符串
.flatMap(lambda line: line.split(" ")) \ # 按空格分割成单词
.map(lambda word: (word, 1)) \ # 转换为 (单词, 1) 的元组
.reduceByKey(lambda a, b: a + b) # 按单词分组求和
# ------------------------------
# 4. 输出结果(可替换为写入数据库、ES 等)
# ------------------------------
processed_stream.foreachRDD(lambda rdd: rdd.foreach(print)) # 输出到控制台
# ------------------------------
# 5. 启动流式计算
# ------------------------------
ssc.start()
ssc.awaitTermination() # 阻塞等待终止
if __name__ == "__main__":
main()
三、启动服务与验证
解释一下这一部分包括了三部分:
启动各个集群,第二部分运行刚才启动的pyspark代码,第三部分在kafka端输入数据模拟
3.1 启动 Kafka(node1)
# 检查 ZooKeeper 和 Kafka 进程(确保已启动)
jps | grep -E 'ZooKeeperServer|Kafka'
3.2 启动 Flume Agent(node2)
cd /opt/flume
# 启动 Flume(后台运行,日志输出到 logs/flume.log)
nohup bin/flume-ng agent \
--name agent1 \
--conf conf/ \
--conf-file conf/kafka-to-spark.conf \
-Dflume.root.logger=INFO,FILE \ # 日志级别为 INFO,输出到文件
> logs/flume.log 2>&1 &
# 验证 Flume 启动成功(查看日志)
tail -f logs/flume.log
# 应看到类似日志:
# INFO source.kafka.KafkaSource: KafkaSource kafka_source started
# INFO sink.AvroSink: Avro Sink avro_sink: Sink to node3:41414 started
3.3. 启动 Spark 集群(node3)
/opt/spark/sbin/start-all.sh # 启动 Master 和 Worker
# 验证 Spark 集群状态(访问 http://node3:8080 查看 Web UI)
jps | grep -E 'Master|Worker'
3.4. 提交 PySpark 应用(node3)
/opt/spark/bin/spark-submit \
--master spark://node3:7077 \ # Spark Master 地址
--py-files /root/spark-apps/flume_kafka_streaming.py \ # 应用代码路径
/root/spark-apps/flume_kafka_streaming.py
# 验证应用启动成功(查看 Spark Web UI 或控制台日志)
# 应看到类似日志:
# INFO streaming.StreamingContext: StreamingContext started
3.5模拟 Hive 数据写入 Kafka(使用 Kafka 控制台生产者)
/opt/kafka/bin/kafka-console-producer.sh \
--bootstrap-server node1:9092 \
--topic hive_data_topic
# 在控制台输入测试数据(每行一条消息):
hive data spark streaming
flume kafka pyspark
hive flume spark
3.6检查 PySpark 接收 Flume 数据
查看 PySpark 应用日志(通过 Spark Web UI 或终端输出):
('hive', 2)
('data', 1)
('spark', 2)
('streaming', 1)
('flume', 2)
('kafka', 1)
('pyspark', 1)
四、总结
1、环境部署:node1 部署 Kafka、node2 部署 Flume、node3 部署 Spark,各组件按节点分工。
2、核心配置:Flume 写配置文件(Source 连 Kafka、Sink 连 Spark 端口),PySpark 代码监听 Flume 的 Avro 端口并处理数据。
3、启动服务:按 Kafka→Flume Agent→Spark 集群顺序启动,通过spark-submit提交 PySpark 代码。
4、结果验证:向 Kafka 发测试数据,检查 Flume 日志(数据拉取)和 PySpark 输出(处理结果)。关键:确保各组件参数一致(如端口、主题),按序启动保障数据流动。