我用的是JupyterHub + PySpark,我想用一些JAR包构建UDF。所以需要将这些JAR包广播到execution节点上。并且我需要用 SparkConf()
来配置,而不是用 spark-submit ... --jars my_jar.jar
这个方法。
我的Spark 版本
sc.version = 3.3.0-SNAPSHOT
conf = SparkConf().setAppName(name).setMaster(url)
conf.set('spark.jars', 'path/my_jar1.jar,path/my_jar2.jar')
conf.set('spark.executor.extraClassPath', 'path')
...
spark.sql("CREATE OR REPLACE FUNCTION my_func AS 'my_class' USING JAR 'path/my_jar1.jar'")
spark.sql("SELECT my_func(col1) FROM my_table")
其中 my_jar1.jar
中的Java文件调用了 my_jar2.jar
中的class文件。
Py4JJavaError: An error occurred while calling o3292.sql.
: java.lang.NoClassDefFoundError: path/to/class/of/my_jar2.jar
my_jar2.jar
没有被广播到execution节点上。导致spark找不到my_jar1.jar
中import的那些的my_jar2.jar的class。
解决这个错误。
自问自答。上面那个错误原因是没有在SQL语句里加入 my_jar2.jar
. 应该将问题中第7行改为:
spark.sql("CREATE OR REPLACE FUNCTION my_func AS 'my_class' USING JAR 'path/my_jar1.jar', JAR 'path/my_jar2.jar'")
resource_locations
Specifies the list of resources that contain the implementation of the function along with its dependencies.
Syntax: USING { { (JAR | FILE ) resource_uri} , ...}
https://spark.apache.org/docs/3.0.0-preview/sql-ref-syntax-ddl-create-function.html