pyflink连接hadoop异常处理

异常明细

Caused by: org.apache.flink.core.fs.UnsupportedFileSystemSchemeException: Could not find a file system implementation for scheme 'hdfs'. The scheme is not directly supported by Flink and no Hadoop file system to support this scheme could be loaded. For a full list of supported file systems, please see https://nightlies.apache.org/flink/flink-docs-stable/ops/filesystems/.

介绍

之前在接触checkpoint时,flink官网中说明,cp建议存储在分布式文件系统中,有介绍使用时直接配置 hdfs 相关地址就行,
例如配置 hdfs://localhost:9000/test/cp_test, 当时因为本地ide中运行时一直无法使用,提示上述的异常, 这个提示其实是缺失hadoop相关 jar包导致的,
在服务器上运行时因为有hadoop环境,且是提交yarn执行,
按照官网yarn提交运行地提示

/etc/profile 中配置后服务器上可以运行

export HADOOP_CLASSPATH=`hadoop classpath`

所以当时是 服务器运行正常,本地无法使用, 当时以为是因为本地没有hadoop环境导致的

最近又碰到有同学本地有 hadoop的情况下提示这个问题,于是想一探究竟

HADOOP_ClASSPATH 的值是什么

本质上是一堆hadoop jar包的地址

# 服务器上运行
hadoop classpath

有时flink需要hadoop,但是它自身里面又不包含它的jar

  • flink 可以提交到yarn集群来管理
  • flink 支持 hdfs 分布式文件格式,例如它的 checkpoint 直接就可以存储到 hdfs中
  • 关键是 flink本身把 hadoop相关包分离出来了,这个建议去看flink的发布记录,里面有记录为啥分离及何时分离

这里我是在使用pyflink时对该问题的解决; 有两种方法

  • 使用封装好的全包装 jar包,例如 flink-shaded-hadoop-2-uber.jar

    • 本地运行时将其放到 pyflink安装目录对应 lib中
    • 提交到服务器集群中运行,放置到对于flink安装目录的 lib中
  • 使用 hadoop 安装包中 jar包

    • 环境变量中配置 HADOOP_ClASSPATH

这里之所有想问这个问题,因为在我已经知道flink缺 jar 的情况下,解决方案就是把 jar 给flink加上,

  • 尝试通过 add_jar的方式加载 flink-shaded-hadoop-2-uber.jar 时:不行
  • 将jar放置在pyflink安装目录对于lib中: 可以

于是我感觉pyflink对于加载hadoop的jar相关时机肯定很重要

要理解这一点,要翻翻pyflink何时加载 HADOOP_ClASSPATH 的源码了

  • 结果发现在初始化env(StreamExecutionEnvironment)时就通过调用函数 construct_hadoop_classpath 已经进行了 hadoop_classpath的使用逻辑,所以加载hadoop_classpath要在env初始化之前

  • 事实上文档中也有所提示在文档高级配置篇中它又有这么一段话

如果你想在Hadoop中使用Flink,你需要有一个包含Hadoop依赖项的Flink设置, 而不是添加Hadoop作为应用程序依赖项。换句话说,Hadoop必须是一个依赖项 Flink系统本身,而不是包含应用程序的用户代码。Flink将使用 由HADOOP_CLASSPATH环境变量指定的Hadoop依赖项,可以这样设置

所有对于 pyflink 加载hadoop包应该是系统启动时初始之前就要准备好jar包了,等到env初始化好之后在add_jar已经没有用了

示例

from pyflink.datastream import StreamExecutionEnvironment
import os


def construct_local_hadoop_classpath(lib_base):
    """
    加载遍历 hadoop jar包,或者直接在目录下放一个 flink-shaded-hadoop-2-uber.jar
    Args:
        lib_base:

    Returns:

    """
    import glob
    dir_list = ["client", "common", "hdfs", "tools", "yarn", "mapreduce"]
    test_jar_patterns = [lib_base + os.sep + x + os.sep + "*" for x in dir_list]
    test_jars = []
    for pattern in test_jar_patterns:
        pattern = pattern.replace("/", os.path.sep)
        test_jars += glob.glob(pattern)
    return os.path.pathsep.join(test_jars)


def test():
    # 加载hadoop的jar包
    # 如果本地能直接执行hadoop命令,
    # os.environ["HADOOP_CLASSPATH"] = os.popen("hadoop classpath").read()
    # 如果本地不能直接运行hadoop命令,就自己组装
    os.environ["HADOOP_CLASSPATH"] = construct_local_hadoop_classpath(
        "/Users/faron/Documents/install/hadoop-3.3.6/share/hadoop")
    env = StreamExecutionEnvironment.get_execution_environment()
    env.set_parallelism(1)
    hdfs_path = "hdfs://localhost:9000/test/a.log"

    data_stream = env.read_text_file(hdfs_path)
    data_stream.print()

    env.execute()


if __name__ == '__main__':
    test()
posted @ 2023-10-20 15:21  faronzz  阅读(97)  评论(0编辑  收藏  举报