ClassNotFound при отправке Spring-boot-fat-jar на спарк - PullRequest
0 голосов
/ 06 июля 2018

когда я собираю толстую банку с помощью пружинной загрузки, ее имя sparker4m-0.0.1.jar

И я "подаю искру" в искровой кластер.

./bin/spark-submit --deploy-mode client --class org.springframework.boot.loader.JarLauncher ~/Desktop/sparker4m-0.0.1.jar --spark.master=spark://172.16.179.52:7077 --source_path=file:///usr/local/spark-2.3.1-bin-hadoop2.7/hdfs_mock/1530842877616 --out_path=file:///usr/local/spark-2.3.1-bin-hadoop2.7/hdfs_mock/153084287761_out --hadoop.home.dir=/usr/local/hadoop

Вы можете видеть, что я использую "--class org.springframework.boot.loader.JarLauncher", потому что это основной класс Spring-boot-jar, а настоящий Main-класс - test.sparker4m.Sparker4mApplication

вот мой код:

@SpringBootApplication
public class Sparker4mApplication {
    public static void main(String[] args) throws Exception{
       ApplicationContext ctx = 
       SpringApplication.run(Sparker4mApplication.class, args);

       SparkConf conf = new SparkConf().setAppName("Test")
                    .setMaster(happyDay.getVal("spark.master"))
                    .set("spark.driver.host", Inet4Address.getLocalHost().getHostAddress());
       JavaSparkContext sc = new JavaSparkContext(conf);

       .........


       JavaPairRDD<String, String> transformed = rdd.mapToPair(new PairFunction<Tuple2<String, PortableDataStream>, String, String>() {
            @Override
            public Tuple2<String, String> call(Tuple2<String, PortableDataStream> tuple2) throws Exception {
                String fname = tuple2._1();
                PortableDataStream content = tuple2._2();
                byte[] bytes = content.toArray();
                String result = YUVSimpleTrans.transform(bytes);
                return new Tuple2<>(fname, result);
            }
        });

        ..........

        .........
    }
}

Все идет хорошо, но, когда Excecutor запускается, выдает исключение:

Caused by: java.lang.ClassNotFoundException: test.sparker4m.Sparker4mApplication$1
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

test.sparker4m.Sparker4mApplication $ 1 является внутренним классом, используемым test.sparker4m.Sparker4mApplication, и это должно быть «new PairFunction , String, String> ()».

Я предполагал, что процесс Executor в spark использует отдельный URLClassLoader для загрузки классов, но все мои классы (sprint-boot-fat-jar) находятся в sparker4m-0.0.1.jar / BOOT-INF / classes , и все мои файлы зависимостей находятся в sparker4m-0.0.1.jar / BOOT-INF / lib , поэтому URLClassLoader не может загрузить класс.

Есть ли хорошая идея для этого? нужна помощь!

1 Ответ

0 голосов
/ 09 июля 2018

Наконец-то есть решение.

Ключи:

  • 1. Он должен использовать uber-jar со всеми классами и ресурсами, а не в "jar lib"
  • 2. Должен понимать, как работает JarLaucher. JarLaucher предлагается "spring-boot-tools", он используется для "createArchive" и URLLoadClass из / BOOT-INF / * (spring-boot 2.x) и запускает истинный основной класс.

Итак, если «1» сделано, «2» не нужно, потому что нам больше не нужен URLLoadClass из / BOOT-INF / *.

Решение: используйте maven-shade-plugin (без spring-boot-maven-plugin), чтобы создать uber-jar и определить свой истинный основной класс ( не JarLaucher) используйте org.apache.maven.plugins.shade.resource.ManifestResourceTransformer в этом плагине.

После всего, что я сделал, я нашел вопрос Отправка jar-файла с пружинной загрузкой в ​​spark-submit уже подходила, но ответ не ясно указывал, что вы должны не используйте $ {start-class} (JarLaucher), но истинный основной класс

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...