2017-01-03 62 views
5

有什麼方法可以在同一個JVM中運行多個Sparkjava服務器實例嗎?我在「插件」軟件中使用,並根據外部環境我的插件的多個實例可能會啓動,然後導致單個JVM中的多個Spark服務器

java.lang.IllegalStateException: This must be done before route mapping has begun 
at spark.SparkBase.throwBeforeRouteMappingException(SparkBase.java:256) 
at spark.SparkBase.port(SparkBase.java:101) 
at com.foo.bar.a(SourceFile:59) 

它通過查看代碼,它在很大程度上圍繞靜態建在我看來,代碼中的字段,所以我正在考慮一個類加載器技巧或與SparkServerFactory在某種程度上消除SparkBase

+0

可能這些實例使用相同的端口號。當你啓動一個spark實例時,它必須在它自己的端口上運行 –

+1

不,它會在你嘗試初始化第二個端口時發生,而不管端口是否相同。第一次初始化將一個標誌設置爲true,並從那時起大部分配置方法被鎖定。 – jabal

+0

我在使用sparkjava運行集成測試時遇到了同樣的問題。作爲解決方法,確保爲maven failsafe插件設置forkCount = 1/reuseForks = false,以在其自己的JVM進程中執行每個測試類(請參閱http://maven.apache.org/surefire/maven-surefire-plugin/examples/叉選項和 - 並行execution.html) – asmaier

回答

4

從星火2.5,你可以使用ignite()

http://sparkjava.com/news.html#spark25released

例子:

public static void main(String[] args) { 
    igniteFirstSpark(); 
    igniteSecondSpark(); 
} 

static void igniteSecondSpark() { 
    Service http = ignite(); 

    http.get("/basicHello", (q, a) -> "Hello from port 4567!"); 
} 

static void igniteFirstSpark() { 
    Service http = ignite() 
         .port(8080) 
         .threadPool(20); 

    http.get("/configuredHello", (q, a) -> "Hello from port 8080!"); 
} 

我個人初始化它們是這樣的:

import spark.Service 

public static void main(String[] args) { 
    Service service1 = Service.ignite().port(8080).threadPool(20) 
    Service service2 = Service.ignite().port(8081).threadPool(10) 
} 

我推薦閱讀how to use those services outside your main method,其中I認爲在這裏會有很好的用處。

1

訣竅是忽略在spark.Spark中執行的Spark周圍的外部靜態shell,並直接與內部spark.webserver.SparkServer一起使用。代碼中有一些需要解決的問題,例如spark.webserver.JettyHandler不是公開的,所以你不能從你的代碼中實例化它,但是你可以將你自己的類放入該包中並將其公開化。

因此,解決辦法是沿着這些路線:

SimpleRouteMatcher routeMatcher1 = new SimpleRouteMatcher(); 
routeMatcher1.parseValidateAddRoute("get '/foo'", "*/*", wrap("/foo", "*/*", (req, res) -> "Hello World 1")); 

MatcherFilter matcherFilter1 = new MatcherFilter(routeMatcher1, false, false); 
matcherFilter1.init(null); 
PublicJettyHandler handler1 = new PublicJettyHandler(matcherFilter1); 
SparkServer server1 = new SparkServer(handler1); 

new Thread(() -> { 
      server1.ignite("0.0.0.0", 4567, null, null, null, null, "/META-INF/resources/", null, new CountDownLatch(1), 
        -1, -1, -1); 
     }).start(); 

而且需要複製wrap方法在你的代碼庫:

protected RouteImpl wrap(final String path, String acceptType, final Route route) { 
     if (acceptType == null) { 
      acceptType = "*/*"; 
     } 
     RouteImpl impl = new RouteImpl(path, acceptType) { 
      @Override 
      public Object handle(Request request, Response response) throws Exception { 
       return route.handle(request, response); 
      } 
     }; 
     return impl; 
    } 

這似乎是一個可行的解決辦法,如果你需要多火花服務器在你的應用程序。