专栏目标
- 通过一个代码样例开始使用pyflink
- 通过阅读pyflink的源码,逐步了解flink的python接口实现
本文使用的flink版本和pyflink版本基于1.10.1
初识Flink
flink作为当前最流行的流批统一的数据计算处理框架,其开箱即用的部署方式(standalone)对于刚刚接触flink的人来说是非常友好和吸引人的。你可以通过地址找到你想要的版本,也可以直接下载编译好的包来进行下载,当然scala源码包也可以下载
flink的部署非常简单,如果你下载好了,你可以直接切换到解压后的目录下 并执行./bin/start-cluster.sh,默认端口为8080
浏览器打开访问一下试试,因为我这边8080被占用,flink会自动往后使用端口,所以我这边是8081
邂逅PyFlink
PyFlink 是什么?这个问题也许会让人感觉问题的答案太明显了,那就是 Flink + Python,也就是 Flink on Python。那么到底 Flink on Python 意味着这什么呢?那么一个非常容易想到的方面就是能够让 Python 用享受到 Flink 的所有功能。其实不仅如此,PyFlink 的存在还有另外一个非常重要的意义就是,Python on Flink,我们可以将 Python 丰富的生态计算能力运行在 Flink 框架之上,这将极大的推动 Python 生态的发展。其实,如果你再仔细深究一下,你会发现这个结合并非偶然。
Python 生态和大数据生态
Pythoh 生态与大数据生态有密不可分的关系,我们先看看大家都在用 Python 解决什么实际问题?通过一份用户调查我们发现,大多数 Python 用户正在解决 ”数据分析“,”机器学习“的问题,那么这些问题场景在大数据领域也有很好的解决方案。那么 Python 生态和大数据生态结合,抛开扩大大数据产品的受众用户之外,对 Python 生态一个特别重要到意义就是单机到分布式的能力增强,我想,这也是大数据时代海量数据分析对 Python 生态的强需求。
阿里技术专家金竹的案例-PyFlink实现CDN日志实时分析
需求说明
将kafka的实时数据经过group 操作之后,将聚合结果存入mysql
代码目录
相信你已经对pyflink以及该项目有了一些自己的认识了,下边直接上代码。初学一个框架的时候,首先看实现效果,这样能快速的有个认知和学习欲望。
记得首先在你的python环境上安装一下pyflink
准备工作-安装pyflink
python3 -m pip install apache-flink
准备工作-准备一个kafka环境以及zk
准备工作-准备connector的包
Flink默认是没有打包connector的,所以我们需要下载各个connector所需的jar包并放入PyFlink的lib目录。首先拿到PyFlink的lib目录的路径:
$ PYFLINK_LIB=`python -c "import pyflink;import os;print(os.path.dirname(os.path.abspath(pyflink.__file__))+'/lib')"`
然后想需要的jar包下载到lib目录中去:
$ cd $PYFLINK_LIB
$ curl -O https://repo1.maven.org/maven2/org/apache/flink/flink-sql-connector-kafka_2.11/1.10.0/flink-sql-connector-kafka_2.11-1.10.0.jar
$ curl -O https://repo1.maven.org/maven2/org/apache/flink/flink-jdbc_2.11/1.10.0/flink-jdbc_2.11-1.10.0.jar
$ curl -O https://repo1.maven.org/maven2/org/apache/flink/flink-csv/1.10.0/flink-csv-1.10.0-sql-jar.jar
$ curl -O https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.19/mysql-connector-java-8.0.19.jar
程序目录如下图,只要三个文件即可
cdn_demo.py
'''
@Date: 2020-06-07 01:00:16
@LastEditors: JingWeiZ
@LastEditTime: 2020-06-07 13:55:32
@FilePath: /flink-learning/cdn_demo.py
'''
import os
from pyflink.datastream import StreamExecutionEnvironment
from pyflink.table import StreamTableEnvironment, EnvironmentSettings
from enjoyment.cdn.cdn_udf import ip_to_province
from enjoyment.cdn.cdn_connector_ddl import kafka_source_ddl, mysql_sink_ddl
# 创建Table Environment, 并选择使用的Planner
env = StreamExecutionEnvironment.get_execution_environment()
t_env = StreamTableEnvironment.create(
env,
environment_settings=EnvironmentSettings.new_instance().use_blink_planner().build())
# 创建Kafka数据源表
t_env.sql_update(kafka_source_ddl)
# 创建MySql结果表
t_env.sql_update(mysql_sink_ddl)
# 注册IP转换地区名称的UDF
t_env.register_function("ip_to_province", ip_to_province)
# 核心的统计逻辑
t_env.from_path("cdn_access_log")\
.select("uuid, "
"client_ip as province, " # IP 转换为地区名称
"response_size, request_time")\
.group_by("province")\
.select( # 计算访问量
"province, count(uuid) as access_count, "
# 计算下载总量
"sum(response_size) as total_download, "
# 计算下载速度
"sum(response_size) * 1.0 / sum(request_time) as download_speed") \
.insert_into("cdn_access_statistic")
# 执行作业
t_env.execute("pyFlink_parse_cdn_log")
cdn_connector_ddl.py
'''
@Date: 2020-06-07 02:23:02
@LastEditors: JingWeiZ
@LastEditTime: 2020-06-07 03:07:35
@FilePath: /flink-learning/enjoyment/cdn/cdn_connector_ddl.py
'''
kafka_source_ddl = """
CREATE TABLE cdn_access_log (
uuid VARCHAR,
client_ip VARCHAR,
request_time BIGINT,
response_size BIGINT,
uri VARCHAR
) WITH (
'connector.type' = 'kafka',
'connector.version' = 'universal',
'connector.topic' = 'access_log',
'connector.properties.zookeeper.connect' = '192.168.1.100:2181',
'connector.properties.bootstrap.servers' = '192.168.1.100:9092',
'format.type' = 'csv',
'format.ignore-parse-errors' = 'true'
)
"""
mysql_sink_ddl = """
CREATE TABLE cdn_access_statistic (
province VARCHAR,
access_count BIGINT,
total_download BIGINT,
download_speed DOUBLE
) WITH (
'connector.type' = 'jdbc',
'connector.url' = 'jdbc:mysql://192.168.1.100:3306/flink',
'connector.table' = 'cdn_access_statistic',
'connector.username' = 'root',
'connector.password' = '123456',
'connector.write.flush.interval' = '1s'
)
"""
cdn_udf.py
'''
@Date: 2020-06-07 02:23:12
@LastEditors: JingWeiZ
@LastEditTime: 2020-06-07 02:23:29
@FilePath: /flink-learning/enjoyment/cdn/cdn_udf.py
'''
import re
import json
from pyflink.table import DataTypes
from pyflink.table.udf import udf
from urllib.parse import quote_plus
from urllib.request import urlopen
@udf(input_types=[DataTypes.STRING()], result_type=DataTypes.STRING())
def ip_to_province(ip):
try:
urlobj = urlopen(
'http://whois.pconline.com.cn/ipJson.jsp?ip=%s' % quote_plus(ip))
data = str(urlobj.read(), "gbk")
pos = re.search("{[^{}]+\}", data).span()
geo_data = json.loads(data[pos[0]:pos[1]])
if geo_data['pro']:
return geo_data['pro']
else:
return geo_data['err']
except:
return "UnKnow"
让程序跑起来
我们让代码跑在standalone的flink上边,这里我用pyflink自带的编译好的flink启动程序
本地运行作业
启动本地集群:
export PYTHONPATH=/Users/zhoujingwei/anaconda3/bin/
export PATH=$PYTHONPATH:$PATH
PYFLINK_LIB=$(python -c "import pyflink;import os;print(os.path.dirname(os.path.abspath(pyflink.__file__))+'/lib')")
$PYFLINK_LIB/../bin/start-cluster.sh
其中PYTHONPATH写上你的python执行器的具体bin目录,注意有多个python的机器上要修改为你安装了pyflink的环境
好了,flink启动之后,就要把我们的job提交到flink上
export PYTHONPATH=/Users/zhoujingwei/anaconda3/bin/
export PATH=$PYTHONPATH:$PATH
PYFLINK_LIB=$(python -c "import pyflink;import os;print(os.path.dirname(os.path.abspath(pyflink.__file__))+'/lib')")
echo $PYFLINK_LIB/../bin/
$PYFLINK_LIB/../bin/flink run -m localhost:8081 -py cdn_demo.py
然后可以看到任务已经提交到flink上了
这个时候你可以试着往kafka topic里边丢一些测试数据
cd /kafka/
./bin/kafka-console-producer.sh --broker-list 192.168.1.1:9092 --topic access_log
>abcd123,1.1.1.1,307,100000,https://www.aaa.com
然后去查看一下flink页面上是否有数据处理
再来看一下我们的mysql表里边有没有存进去把
ok,存进去了,是不是很棒棒鸡!
当然我们用的是stream的api,这个任务只要你不取消他就一直在,后边我们一起分析一下源码以及一些常用的配置。
关注我,一起学pyflink。
参考文章:
1、https://ci.apache.org/projects/flink/flink-docs-release-1.10/api/python/pyflink.datastream.html
2、https://zhuanlan.zhihu.com/p/114717285
3、https://zhuanlan.51cto.com/art/202004/614030.htm
4、https://zhuanlan.zhihu.com/p/105909554
5、https://www.alibabacloud.com/blog/the-flink-ecosystem-a-quick-start-to-pyflink_596150
6、https://flink.apache.org/downloads.html