flink-1.10 pyflink onyarn 安装文档(支持 UDF)

本文详细介绍如何从源码编译Flink,安装配置PyFlink,并在YARN集群上运行Python UDF。涵盖Apache Beam、Python环境打包及独立Python环境的创建与测试,适合初学者快速上手。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

官方文档对 pyflink 的使用说明不是很详细。本文主要参考了 孙金城 大佬的这篇文章
结合自己测试过程,有些地方做了修改,做一个记录

1.从源码编译 flink

注意:需要 Python 3.5+
如果已经有 apache-flink-*.dev0.tar.gz 二进制包,可以跳过这一步。

mvn clean install -DskipTests

会在 flink-python/dist 目录生成一个 apache-flink-*.dev0.tar.gz 二进制包,拷贝该包到需要安装 pyflink 的机器

2.安装并测试

本文只介绍 onyarn 模式的安装、部署
安装机器环境要求:

  • Apache Beam version == 2.15.0
  • Python 3.5+
  • Pip (version >= 7.1.0)
  • hadoop 文件系统

2.1 install pyflink

-i 指定国内 pip 源,安装会快一点

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple  apache-flink-1.10.dev0.tar.gz

2.2 打包 Python 环境

因为 yarn 集群上 python 环境不一定符合 flink 程序的版本要求,所以我们需要使用 virtualenv 打包 python 环境。

2.2.1 install virtualenv
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple  virtualenv
2.2.2 创建 Python 环境

用 virtualenv 以 always-copy 方式建立一个全新的 Python 环境,这里定义名称为 venv:

virtualenv --always-copy venv

会在当前目录生成一个 venv 文件

拷贝原环境的 python 标准库到 venv 中:

VENV_PYTHON=venv/bin/python
DST=`$VENV_PYTHON -c "import os;import pip;print(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(pip.__file__)))))"`
SRC=`$VENV_PYTHON -c "import os;import contextlib;print(os.path.dirname(os.path.abspath(contextlib.__file__)))"`
if [ "$SRC" != "$DST" ]; then find "$SRC" -maxdepth 1 ! -name "site-packages" ! -name "__pycache__" ! -name "python3.*" -exec cp -r -- "{}" "${DST}" \; ; fi
2.2.3 新环境安装 apache-beam

使用 venv 中的 pip 安装 apache-beam

venv/bin/pip install -i https://pypi.tuna.tsinghua.edu.cn/simple apache-beam==2.15.0
2.2.4 打包 Python 环境

把独立 python 环境打成 zip 包,目前打成的包比较大,有 90 多 MB

zip -r venv.zip venv

2.3 例子测试

拷贝下面的代码到 pyflink_job.py 文件:

import logging
import os
import shutil
import sys
import tempfile

from pyflink.table import BatchTableEnvironment, EnvironmentSettings
from pyflink.table.descriptors import FileSystem, OldCsv, Schema
from pyflink.table.types import DataTypes
from pyflink.table.udf import udf


def word_count():
   environment_settings = EnvironmentSettings.new_instance().in_batch_mode().use_blink_planner().build()
   t_env = BatchTableEnvironment.create(environment_settings=environment_settings)

   # register Results table in table environment
   #tmp_dir = tempfile.gettempdir()
   result_path = 'hdfs:///user/flink/python_result'
   #if os.path.exists(result_path):
   #    try:
   #        if os.path.isfile(result_path):
   #            os.remove(result_path)
   #        else:
   #            shutil.rmtree(result_path)
   #    except OSError as e:
   #        logging.error("Error removing directory: %s - %s.", e.filename, e.strerror)

   logging.info("Results directory: %s", result_path)

   # we should set the Python verison here if `Python` not point
   # t_env.get_config().set_python_executable("python3")

   t_env.connect(FileSystem().path(result_path)) \
       .with_format(OldCsv()
                    .field_delimiter(',')
                    .field("city", DataTypes.STRING())
                    .field("sales_volume", DataTypes.BIGINT())
                    .field("sales", DataTypes.BIGINT())) \
       .with_schema(Schema()
                    .field("city", DataTypes.STRING())
                    .field("sales_volume", DataTypes.BIGINT())
                    .field("sales", DataTypes.BIGINT())) \
       .create_temporary_table("Results")

   @udf(input_types=DataTypes.STRING(), result_type=DataTypes.ARRAY(DataTypes.STRING()))
   def split(input_str: str):
       return input_str.split(",")

   @udf(input_types=[DataTypes.ARRAY(DataTypes.STRING()), DataTypes.INT()], result_type=DataTypes.STRING())
   def get(arr, index):
       return arr[index]

   t_env.register_function("split", split)
   t_env.register_function("get", get)

   t_env.get_config().get_configuration().set_string("parallelism.default", "1")

   data = [("iPhone 11,30,5499,Beijing", ),
           ("iPhone 11 Pro,20,8699,Guangzhou", ),
           ("MacBook Pro,10,9999,Beijing", ),
           ("AirPods Pro,50,1999,Beijing", ),
           ("MacBook Pro,10,11499,Shanghai", ),
           ("iPhone 11,30,5999,Shanghai", ),
           ("iPhone 11 Pro,20,9999,Shenzhen", ),
           ("MacBook Pro,10,13899,Hangzhou", ),
           ("iPhone 11,10,6799,Beijing", ),
           ("MacBook Pro,10,18999,Beijing", ),
           ("iPhone 11 Pro,10,11799,Shenzhen", ),
           ("MacBook Pro,10,22199,Shanghai", ),
           ("AirPods Pro,40,1999,Shanghai", )]
   t_env.from_elements(data, ["line"]) \
       .select("split(line) as str_array") \
       .select("get(str_array, 3) as city, "
               "get(str_array, 1).cast(LONG) as count, "
               "get(str_array, 2).cast(LONG) as unit_price") \
       .select("city, count, count * unit_price as total_price") \
       .group_by("city") \
       .select("city, "
               "sum(count) as sales_volume, "
               "sum(total_price) as sales") \
       .insert_into("Results")

   t_env.execute("word_count")


if __name__ == '__main__':
   logging.basicConfig(stream=sys.stdout, level=logging.INFO, format="%(message)s")
   word_count()

执行以下命令,以 per-job 模式提交:

bin/flink run -m yarn-cluster -pyarch venv.zip -pyexec venv.zip/venv/bin/python -py pyflink_job.py

参数说明:

参数说明
-pyarch/–pyArchives venv.zip将当前目录下的 venv.zip 上传到yarn集群. -pyarch/--pyArchives <arg> 可以上传独立 python 环境或者数据文件,并且只能是 zip 压缩格式。flink 将指定的 zip 文件将被解压到 python UDF worker 的工作目录,默认解压目录名和 zip 压缩包名相同,可以通过#指定解压的目录名,例如 -pyarch data.zip#data1将被解压为 data1。还可以使用 , 分隔指定多个 zip 压缩包,例如:-pyarch file:///tmp/py37.zip,file:///tmp/data.zip#data,然后可以通过 -pyexec 指定 python UDF worker 的 python 路径,例如 -pyexec py37.zip/py37/bin/python;python UDF worker 可以通过 f = open('data/data.txt', 'r')方式获取数据文件
-pyexec/–pyExecutable venv.zip/venv/bin/Python指定venv.zip中的Python解释器来执行Python UDF,路径需要和zip包内部结构一致。
-py/–python pyflink_job.py程序入口

flink 还提供了一些其他参数:

参数说明
-pyfs,–pyFiles <pythonFiles>为作业添加自定义的 python 文件,这些文件会被添加到 python UDF woker 的 PYTHONPATH 环境变量,标准 python resource 文件后缀如 .py/.egg/.zip 或者目录都是支持的,可以使用 , 分隔上传多个文件,例如 --pyFiles file:///tmp/myresource.zip,hdfs:///$namenode_address/myresource2.zip
-pym,–pyModule <pythonModule>指定 python 入口文件的 Python module,必须和 --pyFiles 一起使用
-pyreq,–pyRequirements <arg>指定一个 requirements.txt 文件,用来安装第三方依赖,这些依赖会被添加到 python UDF worker 的 PYTHONPATH 环境变量中。用户可以选择的将这些依赖放到一个目录中(python UDF worker 就可以直接用了)用 # 指定要上传的目录。例如 --pyRequirements file:///tmp/requirements.txt#file:///tmp/cached_dir

本文参考
https://enjoyment.cool/2020/01/02/Apache-Flink-%E8%AF%B4%E9%81%93%E7%B3%BB%E5%88%97-PyFlink-%E4%BD%9C%E4%B8%9A%E7%9A%84%E5%A4%9A%E7%A7%8D%E9%83%A8%E7%BD%B2%E6%A8%A1%E5%BC%8F/#more
https://enjoyment.cool/2019/12/05/Apache-Flink-%E8%AF%B4%E9%81%93%E7%B3%BB%E5%88%97-%E5%A6%82%E4%BD%95%E5%9C%A8PyFlink-1-10%E4%B8%AD%E8%87%AA%E5%AE%9A%E4%B9%89Python-UDF

更多内容请关注 大神博客

### 关于ArcGIS License Server无法启动的解决方案 当遇到ArcGIS License Server无法启动的情况,可以从以下几个方面排查并解决问题: #### 1. **检查网络配置** 确保License Server所在的计算机能够被其他客户端正常访问。如果是在局域网环境中部署了ArcGIS Server Local,则需要确认该环境下的网络设置是否允许远程连接AO组件[^1]。 #### 2. **验证服务状态** 检查ArcGIS Server Object Manager (SOM) 的运行情况。通常情况下,在Host SOM机器上需将此服务更改为由本地系统账户登录,并重启相关服务来恢复其正常工作流程[^2]。 #### 3. **审查日志文件** 查看ArcGIS License Manager的日志记录,寻找任何可能指示错误原因的信息。这些日志可以帮助识别具体是什么阻止了许可服务器的成功初始化。 #### 4. **权限问题** 确认用于启动ArcGIS License Server的服务账号具有足够的权限执行所需操作。这包括但不限于读取/写入特定目录的权利以及与其他必要进程通信的能力。 #### 5. **软件版本兼容性** 保证所使用的ArcGIS产品及其依赖项之间存在良好的版本匹配度。不一致可能会导致意外行为完全失败激活license server的功能。 #### 示例代码片段:修改服务登录身份 以下是更改Windows服务登录凭据的一个简单PowerShell脚本例子: ```powershell $serviceName = "ArcGISServerObjectManager" $newUsername = ".\LocalSystemUser" # 替换为实际用户名 $newPassword = ConvertTo-SecureString "" -AsPlainText -Force Set-Service -Name $serviceName -StartupType Automatic New-ServiceCredential -ServiceName $serviceName -Account $newUsername -Password $newPassword Restart-Service -Name $serviceName ``` 上述脚本仅作为示范用途,请依据实际情况调整参数值后再实施。 --- ###
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值