在Java Spark的API文档(不是Apache spark)中,您可以指定端口0以使其自动选择端口。太好了!
但是,我无法弄清楚如何在服务器启动后获取该端口。我可以在日志中看到它:
15:41:12.459 [Thread-2] INFO spark.webserver.JettySparkServer - >> Listening on 0.0.0.0:63134
但是我需要能够以编程方式实现它,以便我的集成测试能够每次都可靠地运行。
那么我该如何获得该端口?
答案 0 :(得分:3)
我无法在API中获取此信息,因此我提交了issue on their github。
我能够通过一堆丑陋的反思得到它:
/**
* Meant to be called from a different thread, once the spark app is running
* This is probably only going to be used during the integration testing process, not ever in prod!
*
* @return the port it's running on
*/
public static int awaitRunningPort() throws Exception {
awaitInitialization();
//I have to get the port via reflection, which is fugly, but the API doesn't exist :(
//Since we'll only use this in testing, it's not going to kill us
Object instance = getInstance();
Class theClass = instance.getClass();
Field serverField = theClass.getDeclaredField("server");
serverField.setAccessible(true);
Object oneLevelDeepServer = serverField.get(instance);
Class jettyServerClass = oneLevelDeepServer.getClass();
Field jettyServerField = jettyServerClass.getDeclaredField("server");
jettyServerField.setAccessible(true);
//Have to pull in the jetty server stuff to do this mess
Server jettyServer = (Server)jettyServerField.get(oneLevelDeepServer);
int acquiredPort = ((ServerConnector)jettyServer.getConnectors()[0]).getLocalPort();
log.debug("Acquired port: {}", acquiredPort);
return acquiredPort;
}
这在我们的集成测试中对我很有用,但我没有使用https,它通过反射抓取受保护的字段确实达到API的两个层次。我找不到任何其他方法来做到这一点。很高兴被证明是错误的。
答案 1 :(得分:1)
这适用于Spark 2.6.0:
public static int start (String keystoreFile, String keystorePw)
{
secure(keystoreFile, keystorePw, null, null);
port(0);
staticFiles.location("/public");
get(Path.CLOCK, ClockController.time);
get(Path.CALENDAR, CalendarController.date);
// This is the important line. It must be *after* creating the routes and *before* the call to port()
awaitInitialization();
return port();
}
如果没有调用awaitInitialization(),port()将返回0。