Spark SQL RDD在pyspark中加载但不在spark-submit中加载:“JDBCRDD:closed connection”

时间:2017-02-16 08:33:48

标签: apache-spark jdbc pyspark

我有以下简单的代码,用于将Postgres数据库中的表加载到RDD中。

# this setup is just for spark-submit, will be ignored in pyspark
from pyspark import SparkConf, SparkContext
from pyspark.sql import SQLContext
conf = SparkConf().setAppName("GA")#.setMaster("localhost")
sc = SparkContext(conf=conf)
sqlContext = SQLContext(sc)

# func for loading table
def get_db_rdd(table):
    url = "jdbc:postgresql://localhost:5432/harvest?user=postgres"
    print(url)
    lower = 0
    upper = 1000
    ret = sqlContext \
      .read \
      .format("jdbc") \
      .option("url", url) \
      .option("dbtable", table) \
      .option("partitionColumn", "id") \
      .option("numPartitions", 1024) \
      .option("lowerBound", lower) \
      .option("upperBound", upper) \
      .option("password", "password") \
      .load()
    ret = ret.rdd
    return ret

# load table, and print results
print(get_db_rdd("mytable").collect())

我运行./bin/pyspark然后将其粘贴到解释器中,并按预期从我的表中打印出数据。

现在,如果我将该代码保存到名为test.py的文件然后执行./bin/spark-submit test.py,它就会开始运行,但之后我会看到这些消息永远发送到我的控制台:

17/02/16 02:24:21 INFO Executor: Running task 45.0 in stage 0.0 (TID 45)
17/02/16 02:24:21 INFO JDBCRDD: closed connection
17/02/16 02:24:21 INFO Executor: Finished task 45.0 in stage 0.0 (TID 45). 1673 bytes result sent to driver

编辑:这是在一台机器上。我没有开始任何主人或奴隶; spark-submit是我在系统启动后运行的唯一命令。我尝试使用相同的结果进行主/从设置。 我的spark-env.sh文件如下所示:

export SPARK_WORKER_INSTANCES=2
export SPARK_WORKER_CORES=2
export SPARK_WORKER_MEMORY=800m
export SPARK_EXECUTOR_MEMORY=800m
export SPARK_EXECUTOR_CORES=2
export SPARK_CLASSPATH=/home/ubuntu/spark/pg_driver.jar # Postgres driver I need for SQLContext
export PYTHONHASHSEED=1337 # have to make workers use same seed in Python3

如果我点火提交一个只从列表或其他东西创建RDD的Python文件,它就有效。我尝试使用JDBC RDD时只遇到问题。我错过了什么?

2 个答案:

答案 0 :(得分:1)

使用spark-submit时,您应该向执行者提供jar

spark 2.1 JDBC documents中所述:

  

要开始使用,您需要为您提供JDBC驱动程序   spark类路径上的特定数据库。例如,要连接到   来自Spark Shell的postgres,您将运行以下命令:

bin/spark-shell --driver-class-path postgresql-9.4.1207.jar --jars postgresql-9.4.1207.jar
  

注意:同样适用于spark-submit命令

<强>疑难解答

  

JDBC驱动程序类必须对原始类加载器可见   在客户端会话和所有执行程序上。这是因为Java的   DriverManager类执行安全检查,导致它忽略   一个人去的时候,所有的驱动程序对原始类加载器都不可见   打开连接。 一种方便的方法是修改   所有工作节点上的 compute_classpath.sh包含您的驱动程序JAR。

答案 1 :(得分:0)

这是一个可怕的黑客。我不是在考虑这个答案,但确实有效。

好吧,只有pyspark有效吗?好的,我们会用它。写了这个Bash脚本:

cat $1 | $SPARK_HOME/bin/pyspark # pipe the Python file into pyspark

我在提交作业的Python脚本中运行该脚本。另外,我包含了用于在进程之间传递参数的代码,以防它帮助某人:

new_env = os.environ.copy()
new_env["pyspark_argument_1"] = "some param I need in my Spark script" # etc...
p = subprocess.Popen(["pyspark_wrapper.sh {}".format(py_fname)], shell=True, env=new_env)

在我的Spark脚本中:

something_passed_from_submitter = os.environ["pyspark_argument_1"]
# do stuff in Spark...

我觉得Spark更好地受到支持,并且(如果这是一个错误)Scala的错误少于Python 3,所以这可能是现在更好的解决方案。但是我的脚本使用了我们在Python 3中编写的一些文件,所以......