Apache Spark MySQL JavaRDD.foreachPartition - 为啥我得到 ClassNotFoundException

Posted

技术标签:

【中文标题】Apache Spark MySQL JavaRDD.foreachPartition - 为啥我得到 ClassNotFoundException【英文标题】:Apache Spark MySQL JavaRDD.foreachPartition - why I getting ClassNotFoundExceptionApache Spark MySQL JavaRDD.foreachPartition - 为什么我得到 ClassNotFoundException 【发布时间】:2015-05-06 16:10:59 【问题描述】:

我想将每个分区的数据保存到 mysql 数据库。为此,我创建了实现 VoidFunction<> 的类:

public class DatabaseSaveFunction implements VoidFunction<Iterator<String>> 

    /**
     * 
     */
    private static final long serialVersionUID = -7039277486852158360L;

    public void call(Iterator<String> it) 
        Connection connect = null;
        PreparedStatement preparedStatement = null;

        try 
            Class.forName("com.mysql.jdbc.Driver");
            connect = DriverManager.getConnection("jdbc:mysql://"
                    + "xxx.us-west-2.rds.amazonaws.com" + "/"
                    + "xxx", "xxx", "xxx");

            preparedStatement = connect
                    .prepareStatement("insert into  testdatabase.test values (default, ?)");

            while (it.hasNext()) 
                String outputElement = it.next();
                preparedStatement.setString(1, "" + outputElement.length());
                preparedStatement.executeUpdate();
            

         catch (ClassNotFoundException e) 
            e.printStackTrace();
         catch (SQLException e) 
            e.printStackTrace();
         finally 
            try 
                connect.close();
                preparedStatement.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
    

在我调用的主要方法类中:

output.foreachPartition(new DatabaseSaveFunction());

我收到以下错误:

15/05/06 15:34:00 WARN scheduler.TaskSetManager: Lost task 0.0 in stage 1.0 (TID 4, ip-172-31-36-44.us-west-2.compute.internal): java.lang.ClassNotFoundException: DatabaseSaveFunction
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:274)

工人日志:

15/05/06 15:34:00 ERROR executor.Executor: Exception in task 1.0 in stage 1.0 (TID 5)
java.lang.ClassNotFoundException: DatabaseSaveFunction
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:274)

谁能告诉我我做错了什么?对此我将不胜感激。

【问题讨论】:

你是如何编译你的应用程序的? 1.使用 jar -tf 命令检查你的 jar,看看这些类是否真的存在! 2. 改用 maven 程序集,这样您就可以将所有外部 jar 包含到您的应用程序中! 我的 jar 中有 DatabaseSaveFunction.class。如何创建程序集? mysql连接器似乎没有问题。我评论了与之相关的所有代码,问题仍然出现。还有其他想法吗? 您确定您的 spark-ec2 命令中的类路径吗? 你是如何运行应用程序的?使用spark-submit?确切的命令行是什么?如果您不使用spark-submit,则必须使用SparkConf.addJars 要求Spark 将您的东西分发给执行者。 【参考方案1】:

将外部类导出到 jar 并添加类似 sc.addJar("/path/x.jar") 的内容,其中 sc 是您的 main 中的 JavaSparkContext。然后你不会得到这个错误。该错误是因为您的 spark 程序无法找到该类。此外,在 spark 1.3 及更高版本中,您可以简单地使用 jdbc 的映射选项,然后使用 load("jdbc", options) 创建数据框并从任何 RDBMS 加载数据。它真的很方便。我不确定这种方法是否适用于将任何 RDBMS 连接到 spark 中。如果您有任何其他问题,请告诉我。

【讨论】:

以上是关于Apache Spark MySQL JavaRDD.foreachPartition - 为啥我得到 ClassNotFoundException的主要内容,如果未能解决你的问题,请参考以下文章

sparkStraming存储数据到mysql

spark读取mysql

Spark与mysql整合

Apache Spark MySQL JavaRDD.foreachPartition - 为啥我得到 ClassNotFoundException

如何有效地将 MySQL 表读入 Apache Spark/PySpark?

spark写mysql