Spark Streaming+kafka任务实践
任务描述
Spark Streaming + Kafka(但是Python)
1. 使用Apache Kafka构建实时数据流
参考文档链接:https://cloud.tencent.com/developer/article/1814030
2. 数据见UserBehavior.csv
数据解释:本次实战用到的数据集是CSV文件,里面是一百零四万条淘宝用户行为数据,该数据来源是阿里云天池公开数据集
根据这一csv文档运用Kafka模拟实时数据流,作为Spark Streaming的输入源,两条记录实际的间隔时间如果是1分钟,那么Java应用在发送消息时也可以间隔一分钟再发送。
要求
- • 找出最受欢迎的前三名商品ID
- • 找出订单数量最多的日期。
环境使用的配置清单(大概)
- 操作系统:Windows 10
- 编程语言:Python 3
- IDE:PyCharm2021,
- 解释器:python3(但是配置的远程虚拟机上的python),如果是本地模式可以直接用本机python
- 基于Kafka2.12_2.4.1+Spark3.1.2+Hadoop3.1.2+zookeeper平台
- Python包 依赖 kafka-python,pyspark,Kafka—Spark连接依赖包(放到Spark的jar包目录)
代码展示
数据生产者:
import csv
import json
import time
from kafka import KafkaProducer
# 配置Kafka连接信息
bootstrap_servers = 'node1:9092' #broke监听地址信息
topic = 'flink-user-behavior' #主题信息
# 创建Kafka生产者
producer = KafkaProducer(bootstrap_servers=bootstrap_servers,
value_serializer=lambda v: json.dumps(v).encode('utf-8'))
# 读取CSV文件并逐条上传数据到Kafka,这里我直接将csv文件放到了代码文件同一位置,你可以使用绝对路径来试试
with open('UserBehavior.csv', 'r') as file:
reader = csv.reader(file)
#header = next(reader) # 文件没有表头无需跳过头行
prev_timestamp = None # 上一条数据的时间戳
for row in reader:
user_ID, product_ID, productsort_ID, behavior_data, time_data, date_string = row
# 计算当前记录与上一条记录的时间差,以秒为单位
current_timestamp = int(time_data)
if prev_timestamp is not None:
time_diff = current_timestamp - prev_timestamp
# 如果时间差大于一分钟,则延迟一分钟上传
if time_diff > 60:
time.sleep(60)
# 构建JSON对象
data = {
'user_ID': int(user_ID),
'product_ID': int(product_ID),
'productsort_ID': int(productsort_ID),
'behavior_data': behavior_data,
'time_data': int(time_data),
'date_string': date_string
}
# 序列化为JSON并发送到Kafka
producer.send(topic, value=data)
# 更新上一条记录的时间戳
prev_timestamp = current_timestamp
# 文件数据上传结束 关闭Kafka生产者
producer.close()
数据消费者代码:
from pyspark.sql import SparkSession
from pyspark.sql.functions import *
from pyspark.sql.types import *
# 创建SparkSession
spark = SparkSession.builder.appName("RealTimeAnalytics").getOrCreate()
# 配置Kafka连接信息
bootstrap_servers = 'node1:9092'
topic = 'flink-user-behavior'
# 定义Schema,根据实际数据结构进行调整
schema = StructType([
StructField("user_ID", IntegerType()),
StructField("product_ID", IntegerType()),
StructField("productsort_ID", IntegerType()),
StructField("behavior_data", StringType()),
StructField("time_data", IntegerType()),
StructField("date_string", StringType())
])
# 读取Kafka流数据
df1 = spark.readStream.format("kafka") \
.option("kafka.bootstrap.servers", bootstrap_servers) \
.option("subscribe", topic) \
.load() \
.selectExpr("CAST(value AS STRING)")
# 解析JSON数据
parsed_df0 = df1.select(from_json(col("value"), schema).alias("data")) \
.select("data.*")
#parsed_df0.printSchema()#检查信息表创建是否正常
#parsed_df.printSchema()
parsed_df = parsed_df0.withColumn('date', to_date('date_string', 'yyyy/M/d H:m')).select("*")#将日期字符串修改为时间数据,不要忘记添加格式'yyyy/M/d H:m'
# # 检查数据是否整合好
total_amount_df = parsed_df.select(col("*"))
# 找出订单数量最多的日期
most_orders_date_df = parsed_df.groupBy("date") \
.agg(count(col("product_ID")).alias("order_count")) \
.orderBy(col("order_count").desc()) \
.limit(1)
# 找出最受欢迎的前三名商品ID
popular_products_df = parsed_df.groupBy("product_ID") \
.count() \
.withColumnRenamed("count", "popularity") \
.orderBy(col("popularity").desc()) \
.limit(3)
# 启动流计算并输出结果
query1 = total_amount_df.writeStream \
.outputMode("append") \
.format("console") \
.option("truncate", "false") \
.start()
query2 = most_orders_date_df.writeStream \
.outputMode("complete") \
.format("console") \
.option("truncate", "false") \
.start()
query4 = popular_products_df.writeStream \
.outputMode("complete") \
.format("console") \
.option("truncate", "false") \
.start()
# 计算商品热度并输出结果
query2.awaitTermination()
运行结果图片展示
数据生产者控制台:(我用的是linux服务器集群模式搭建的平台系统,并配置了远程主机运行,所以会这样显示)生产者读取数据,根据数据时间戳的差值来延迟上传数据到kafka中
数据消费者控制台:第11次流处理
时间戳差值小于等于1分钟同时上传的记录证实
时间戳相差超过一分钟延时一分钟再上传数据
消费者实时计算数据流显示订单最多的日期和最受欢迎的前三商品id
实际运行能够做到每上传一条数据就进行实时计算,所以可以做到一分钟后上传的数据就一分钟后进行计算,立刻上传的数据,可以立刻计算。
总结
之前参考了scala项目的代码,发现还是python的简洁易用,不过不同语言各有不同的开发优势,不能片面的评价一个语言的优劣,只能说用python写不容易因为一些环境的配置而感到脑淤血,只需要添加好包环境就行。而之前弄java的项目环境配的,也不能说很难,但是很容易脑淤血。弄不好一个下午就这么耗下去了。
这次项目用到的环境搭建还是挺顺利的,必须确保本地的Hdfs+Spark能正常运行,同时python3有pip install 相应的依赖包,然后再启动zookeeper正常运行Kafka进程,配置好主题和监听地址,就可以正常运行以上代码。如果大家对我的环境搭建感兴趣,不用多说,call me!!
分享就到这里,希望各位在大数据开发之路勇往直前的伙伴们都能披荆斩棘!!