2015-07-16 4 views
8

Ho sviluppato un'applicazione Web con Spring Boot che utilizza Apache Spark per interrogare i dati da origini dati diverse (come Oracle). All'inizio, avevo pianificato di eseguire l'applicazione senza inviarla usando lo script spark-submit, ma sembra che non possa connettermi al cluster Master senza inviare un jar. Ho generato con successo un jar uber che include tutte le dipendenze e i sottoprogetti che sto usando, ma sembra che allo Spark non piacciano le applicazioni Spring Boot. Quando cerco di inviare l'applicazione, scintilla mostra il seguente errore:Impossibile inviare l'applicazione java Spring boot al cluster 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) 

Utilizzando profilo predefinito log4j Spark: org/apache/scintilla/log4j-defaults.properties

ho cercato di escludere la slf4j- log4j12 dipendenza nel file pom, ma sto ancora ricevendo lo stesso errore.

Il file pom contiene la seguente configurazione:

<?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> 

C'è un modo per presentare una domanda di avvio di primavera al cluster? Dovrei usare un altro tipo di progetto tenendo conto che ho bisogno di esporre un'API RESTful? C'è un modo per connettersi allo spark cluster senza inviare il .jar?

Grazie in anticipo per il vostro aiuto.

risposta

4

ho avuto un problema simile, per risolverlo provare a rimuovere primavera avvio la registrazione con la seguente esclusione:

<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> 

Se viene ancora un errore durante l'inizializzazione del servlet

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

Quindi provare a utilizzare la versione 1.2.1.RELEASE del genitore starter, poiché ciò è causato dalla versione servlet-api usata da Spark Cluster.

+0

Questa è esattamente la soluzione per il mio problema. Ciao 5! –

1

A Spring Boot in fase di compilazione, viene visualizzato se è stata inclusa una particolare implementazione di registrazione nella build e, in caso contrario, utilizza Logback per impostazione predefinita. Apparentemente Spark sta aggiungendo Log4J al classpath durante l'esecuzione dell'applicazione, che a sua volta causa un errore di run-time perché Spring Boot trova ora due implementer di logger sul classpath: quello incluso in build-time (Logback) e quello Spark è aggiunta in fase di esecuzione (Log4J).

Se Spark fornisce un modo per sopprimere l'inclusione di Log4J in fase di esecuzione, è possibile farlo e lasciare semplicemente il collegamento Spring Boot in Logback per impostazione predefinita.

Se Spark sta forzando Log4J su di te, la soluzione sarebbe includere esplicitamente Log4J (non Logback) nella tua build in modo che Spring Boot la "vedrà" come un build-time, e quindi non includerà Logback.

EDIT: avrei dovuto verificare la mia ipotesi guardando i documenti di avvio di primavera. Devi anche escludere esplicitamente Log4J. Vedi Spring Boot's Logging Docs.

+0

Caro RichW. Ho seguito il secondo approccio che hai suggerito (se Spark ti sta costringendo Log4J, la soluzione sarebbe includere esplicitamente Log4J (non Logback) nella tua build in modo che Spring Boot la "vedrà" come un build-time, e quindi non includerà Logback), ma il problema purtroppo rimane. Questo è il modo ho aggiunto esplicitamente il Log4j di dipendenze: ' log4j log4j ' Sai cosa altro potrei provare? –

+0

Mi dispiace, Stefan, io ho sbagliato. Ho modificato la mia risposta. – RichW

0

Spark supporta solo log4j. Per forzare l'avvio di primavera a utilizzare log4j anziché logback per impostazione predefinita, applicare this procedure from spring-boot reference documentation ma assicurarsi di modificare log4j2 in log4j e dargli una versione, ad es. 1.2.17. Sarà inoltre necessario inserire un file log4j.properties in src/main/resources. È possibile copiare log4j.properties.modello dalla cartella Spark/conf e rinominarlo in log4j.properties.