简体   繁体   English

无法将Spring Boot Java应用程序提交到Spark集群

[英]Unable to submit Spring boot java application to Spark cluster

I have developed a web application with Spring Boot that uses Apache Spark for querying data from different datasources (like Oracle). 我使用Spring Boot开发了一个Web应用程序,该应用程序使用Apache Spark来查询来自不同数据源(例如Oracle)的数据。 At the beginning, I had planned to run the application without submitting it using the spark-submit script, but it looks like I cannot connect to the Master cluster without submitting a jar. 开始时,我曾计划运行应用程序而不使用spark-submit脚本提交应用程序,但是看起来如果不提交jar便无法连接到主集群。 I have successfully generated an uber jar which includes all the dependencies and sub-projects that I am using, but it seems that Spark does not like Spring Boot applications. 我已经成功生成了一个uber jar,其中包含我正在使用的所有依赖项和子项目,但是Spark似乎不喜欢Spring Boot应用程序。 When I try to submit the app, spark shows the following error: 当我尝试提交应用程序时,spark显示以下错误:

Exception in thread "main" java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.impl.Log4jLoggerFactory loaded from file:/home/rojasmi1/spark/spark-1.4.0/assembly/target/scala-2.10/spark-assembly-1.4.0-hadoop2.2.0.jar). If you are using Weblogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml Object of class [org.slf4j.impl.Log4jLoggerFactory] must be an instance of class ch.qos.logback.classic.LoggerContext
at org.springframework.util.Assert.isInstanceOf(Assert.java:339)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:151)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLogger(LogbackLoggingSystem.java:143)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:89)
at org.springframework.boot.logging.LoggingApplicationListener.onApplicationStartedEvent(LoggingApplicationListener.java:152)
at org.springframework.boot.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:139)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128)
at org.springframework.boot.context.event.EventPublishingRunListener.publishEvent(EventPublishingRunListener.java:100)
at org.springframework.boot.context.event.EventPublishingRunListener.started(EventPublishingRunListener.java:54)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:277)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
at ch.dlx.QubidaOracleConnectorApplication.main(QubidaOracleConnectorApplication.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:664)
at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:169)
at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:192)
at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:111)
at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)

Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties 使用Spark的默认log4j配置文件:org / apache / spark / log4j-defaults.properties

I have tried to exclude the slf4j-log4j12 dependency in the pom file, but I am still getting the same error. 我试图在pom文件中排除slf4j-log4j12依赖性,但是我仍然遇到相同的错误。

The pom file contains the following configuration: pom文件包含以下配置:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>ch.dlx</groupId>
<artifactId>qubida-oracle-connector</artifactId>
<version>0.0.1-SNAPSHOT</version>

<name>qubida-oracle-connector</name>
<description></description>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>1.2.5.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>log4j-over-slf4j</artifactId>
            </exclusion>

        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- Spark -->

    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-core_2.11</artifactId>
        <version>1.4.0</version>
        <scope>provided</scope>
        <exclusions>
                    <exclusion>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-sql_2.11</artifactId>
        <version>1.4.0</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-hadoop-core</artifactId>
        <version>1.3.0</version>
        <exclusions>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>log4j-over-slf4j</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- DB Drivers -->

    <dependency>
        <groupId>com.oracle</groupId>
        <artifactId>ojdbc14</artifactId>
        <version>10.2.0.4.0</version>
    </dependency>


</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
                <keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>

                <artifactSet>
                    <excludes>
                        <exclude>org.slf4j</exclude>
                    </excludes>
                </artifactSet>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Is there a way to submit a Spring Boot application to the cluster? 有没有办法将Spring Boot应用程序提交到集群? Should I use another type of project taking into account that I need to expose a RESTful API? 是否应该考虑需要公开RESTful API的其他类型的项目? Is there a way for connecting to the spark cluster without submitting the .jar? 有没有一种方法可以在不提交.jar的情况下连接到spark集群?

Thanks in advance for your help. 在此先感谢您的帮助。

I had a similar issue, for solving it try removing Spring Boot logging with the following exclusion: 我有一个类似的问题,要解决该问题,请尝试使用以下排除方法删除Spring Boot日志记录:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

If you still get an error while initializing the servlet 如果在初始化servlet时仍然出现错误

java.lang.NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName()Ljava/lang/String; java.lang.NoSuchMethodError:javax.servlet.ServletContext.getVirtualServerName()Ljava / lang / String;

Then try using the 1.2.1.RELEASE version of the starter parent, since that is caused because of the servlet-api version used by the Spark Cluster. 然后尝试使用入门级父级的1.2.1.RELEASE版本,因为这是由Spark Cluster使用的servlet-api版本引起的。

At build-time Spring Boot looks to see if you've included a particular logging implementation in your build and, if you haven't, uses Logback by default. 在构建时,Spring Boot会查看您的构建中是否包含了特定的日志记录实现,如果尚未包含,则默认使用Logback。 Apparently Spark is adding Log4J to the classpath when running your application, which in turn causes a run-time error because Spring Boot now finds two logger implementions on the classpath: the one it included at build-time (Logback) and the one Spark is adding at run-time (Log4J). 显然,Spark在运行应用程序时将Log4J添加到类路径中,这又会导致运行时错误,因为Spring Boot现在在类路径上找到两个记录器实现:一个是在构建时包含的(Logback),另一个是在运行时添加(Log4J)。

If Spark provides a way to suppress the inclusion of Log4J at run-time, you could do that and just let Spring Boot wire in Logback by default. 如果Spark提供了一种在运行时禁止包含Log4J的方法,则可以这样做,并且默认情况下只需让Spring Boot连接到Logback中即可。

If Spark is forcing Log4J on you, then the solution would be to explicitly include Log4J (not Logback) in your build so that Spring Boot will "see" it a build-time, and thus not include Logback. 如果Spark强迫您使用Log4J,那么解决方案将是在您的构建中显式包括Log4J(而不是Logback),以便Spring Boot在构建时“看到”它,因此不包括Logback。

EDIT: I should have checked my assumption by looking at the Spring Boot docs. 编辑:我应该已经通过查看Spring Boot文档检查了我的假设。 You also have to explicitly exclude Log4J. 您还必须明确排除Log4J。 See Spring Boot's Logging Docs . 参见Spring Boot的Logging Docs

Spark supports log4j only. Spark仅支持log4j。 In order to force spring-boot to use log4j instead of logback by default, apply this procedure from spring-boot reference documentation but make sure to change log4j2 to log4j and give it a version, eg 1.2.17. 为了强制spring-boot默认使用log4j而不是logback,请从spring-boot参考文档中应用此过程,但请确保将log4j2更改为log4j,并为其提供一个版本,例如1.2.17。 You will also need to put a log4j.properties file in src/main/resources . 您还需要将log4j.properties文件放在src/main/resources You can copy log4j.properties.template from Spark's /conf directory and rename it to log4j.properties. 您可以从Spark的/ conf目录复制log4j.properties.template并将其重命名为log4j.properties。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM