在编写代码Spark应用时出现以上的问题,最后发现是因为Dataset<Row>的foreach方法中传入的参数ForeachFunction<Row>引起的,代码如下:
    projectDataSourceDFFromMySQL.foreach(new ForeachFunction<Row>() {
            private static final long serialVersionUID = 4222182685492143838L;
            public void call(Row t) throws Exception {
                String id = t.getString(0);
                System.out.println(id);
            }
        });
   我分析原因是:这里的实现了接口ForeachFunction的内部类在运行的时候Master会将其序列化传给Slave,因此这个类必须要序列化,但是内部类序列化的时候需要其所寄宿的外部类的对象,而我这个外部类并没有实现Serializable接口,因此无法序列化,则会报上边的错误,将外部类实现Serializable接口后则问题解决。
   按照上边的分析,如果我单独将ForeachFunction接口实现成一个类是不是就不需要让宿主类实现Serializable接口了呢?于是实现了一个类,代码如图:
    public class ForeachFunTest implements ForeachFunction<Row> {
    private static final long serialVersionUID = -4892194648703458595L;

    public void call(Row t) throws Exception {
        String id = t.getString(0);
        System.out.println(id);
    }

}
    然后foreach的地方改为:
    projectDataSourceDFFromMySQL.foreach(new ForeachFunTest());
    的确,这时之前的宿主类就不需要实现Serializable接口了。由此可以得出一个结论,如果这个ForeachFunction中引入的所有的变量都必须是可序列化的,而且变量对应的类也必须放在Slave的类加载器下,因为在Slave那端反序列化的时候要用到这些类的Class信息。当然了,报这个错误也有其他原因,我这里叙述的算是其中的一个。也不是啥高大上的知识点,希望能解决一些人的疑惑,抛砖引玉。
Logo

更多推荐