【问题标题】:Working with jdbc jar in pyspark在 pyspark 中使用 jdbc jar
【发布时间】:2016-07-19 11:22:24
【问题描述】:

我需要从 pyspark 中的 postgres sql 数据库中读取数据。 我知道这在herehere 和许多其他地方已经被问过,但是,那里的解决方案要么使用本地运行目录中的 jar,要么手动将其复制到所有工作人员。

我下载了 postgresql-9.4.1208 jar 并将其放在 /tmp/jars 中。然后我继续使用 --jars 和 --driver-class-path 开关调用 pyspark:

pyspark --master yarn --jars /tmp/jars/postgresql-9.4.1208.jar --driver-class-path /tmp/jars/postgresql-9.4.1208.jar

在 pyspark 里面我做了:

df = sqlContext.read.format("jdbc").options(url="jdbc:postgresql://ip_address:port/db_name?user=myuser&password=mypasswd", dbtable="table_name").load()
df.count()

但是,虽然使用 --jars 和 --driver-class-path 对我创建的 jar 工作正常,但它对 jdbc 失败,并且我从工作人员那里得到了一个异常:

 java.lang.IllegalStateException: Did not find registered driver with class org.postgresql.Driver

如果我手动将 jar 复制到所有工作人员并添加 --conf spark.executor.extraClassPath 和 --conf spark.driver.extraClassPath,它确实有效(使用相同的 jar)。 documentation btw 建议使用已弃用的 SPARK_CLASSPATH 实际上添加了这两个开关(但具有防止使用我需要做的 --jars 选项添加其他 jars 的副作用)

所以我的问题是:jdbc 驱动程序有什么特别之处使其无法正常工作,如何添加它而无需手动将其复制给所有工作人员。

更新:

我做了更多查找并在文档中找到了这个: “JDBC 驱动程序类必须对客户端会话和所有执行程序上的原始类加载器可见。这是因为 Java 的 DriverManager 类会进行安全检查,导致它忽略所有对原始类加载器不可见的驱动程序。打开一个连接。一种方便的方法是修改所有工作节点上的 compute_classpath.sh 以包含您的驱动程序 JAR。”。

问题是我似乎找不到computer_classpath.sh,也不明白原始类加载器的含义。

我确实找到了this,它基本上解释了这需要在本地完成。 我还找到了this,它基本上说有一个修复,但它在 1.6.1 版本中还没有。

【问题讨论】:

    标签: postgresql jdbc apache-spark pyspark pyspark-sql


    【解决方案1】:

    我认为这是此处描述和修复的问题的另一种表现形式:https://github.com/apache/spark/pull/12000。我在 3 周前编写了该修复程序,但没有任何进展。也许如果其他人也表达了他们受到影响的事实,这可能会有所帮助?

    【讨论】:

    • 我想知道为什么有人做了 -1,因为你正确地报告它是 Spark 回归
    【解决方案2】:

    我找到了一个可行的解决方案(不知道它是否是最好的,所以请随时继续评论)。 显然,如果我添加选项:driver="org.postgresql.Driver",这可以正常工作。即我的完整线路(在 pyspark 内)是:

    df = sqlContext.read.format("jdbc").options(url="jdbc:postgresql://ip_address:port/db_name?user=myuser&password=mypasswd", dbtable="table_name",driver="org.postgresql.Driver").load()
    df.count()
    

    另一件事:如果您已经在使用自己的 fat jar(我在我的完整应用程序中),那么您需要做的就是将 jdbc 驱动程序添加到您的 pom 文件中:

        <dependency>
          <groupId>org.postgresql</groupId>
          <artifactId>postgresql</artifactId>
          <version>9.4.1208</version>
        </dependency>
    

    然后您不必将驱动程序添加为单独的jar,只需使用带有依赖项的jar即可。

    【讨论】:

    • 这正是该回归的“官方”解决方法,它似乎特定于 Spark 1.6.1,如 SPARK-14204 中所述 c/o Kevin McHale @987654321 @
    • 我真的希望我能理解它是如何工作的,因为我无法获取不是 JDBC 驱动程序的 Java 代码来加载。事实上,如果我尝试从 py4j 获取驱动程序类,它会告诉我找不到该类。 JDBC 驱动程序是否使用不同的 py4j 网关?
    【解决方案3】:

    您正在查看哪个版本的文档? 似乎compute-classpath.sh 不久前被弃用了——从 Spark 1.3.1 开始:

    $ unzip -l spark-1.3.1.zip | egrep '\.sh' | egrep classpa
     6592  2015-04-11 00:04   spark-1.3.1/bin/compute-classpath.sh
    
    $ unzip -l spark-1.4.0.zip | egrep '\.sh' | egrep classpa
    

    什么都不生产。

    我认为你应该使用 load-spark-env.sh 来设置你的类路径:

    $/opt/spark-1.6.0-bin-hadoop2.6/bin/load-spark-env.sh
    

    您需要在您的 $SPARK_HOME/conf/spark-env.sh 文件中设置 SPARK_CLASSPATH(您将从模板文件 $SPARK_HOME/conf/spark-env.sh.template 复制该文件)。

    【讨论】:

    • 您可以从我的链接中看到(在此重复:spark.apache.org/docs/latest/…)我查看了最新的文档(请参阅故障排除部分)。整个部分都有已弃用的元素(正如我所说,它仍然有 SPARK_CLASSPATH 也已弃用)
    • 你是对的。我能够成功取回结果 - 尽管在本地主机上运行纱线:&gt;&gt;&gt; df = sqlContext.read.format("jdbc").options(url="jdbc:postgresql://localhost/myprojects?user=XXX&amp;password=XXX", dbtable="django_session").load() &gt;&gt;&gt; df.count &lt;bound method DataFrame.count of DataFrame[session_key: string, session_data: string, expire_date: timestamp]&gt;&gt;&gt;&gt; df.count() 4
    猜你喜欢
    • 1970-01-01
    • 2015-09-08
    • 2015-05-27
    • 2015-09-14
    • 2020-02-17
    • 2021-06-01
    相关资源
    最近更新 更多