Spring Bootのアプリケーションで、同じアプリケーションを複数のポートでリッスンさせたいという要件があり、調べてみました。
英語のサイトなどでサンプルがあったものの、Spring Boot 2.x系ですぐに使えるサンプルがなかったのでこちらで紹介しておきます。
要件、前提など
- Spring Boot 2.x (実際に使用したのは2.1.2.RELEASE)
- 一つのインスタンスで複数ポートをリッスンさせたい、例: 8654, 30212, 30224
- 接続はプレーンなHTTPでSSLは必要ない
Spring Bootのポートを変更する方法
まず、Spring Bootでサーバーのポートを変更する方法を確認しておきましょう。
Spring Bootは、何も指定しないとデフォルトでポート8080が使用されます。
このポートの設定は、application.propertiesまたはapplication.ymlファイルで上書きできます。
設定ファイルで上書きする方法
application.ymlの場合
server:
port: 8081
application.propertiesの場合
server.port=8081
コマンドラインで実行時に指定する方法
実行時のコマンドラインオプションでポートを指定することもできます。例えば
my-application.jar --server.port=8081
といった感じですね。
ランダムなポートを使用する場合
ポート番号を0にすると、ランダムな空きポートが使用されます。ローカルな開発環境やテスト時に使用されるかもしれません。
複数のポートをリッスンさせる方法
server.port のプロパティを使うとポートを変更することはできますが、複数のポートで待ち受けることはできません。
これを変更するにはコードを書く必要があります。
Spring Bootは、デフォルトでTomcatを使用するので、Tomcatに複数のコネクターを作成して、それぞれにポートを割り当てる必要があります。
以下は、その設定を行うコードです。
@Configuration
public class EmbeddedTomcatConfiguration implements WebMvcConfigurer {
@Value("${server.port:8080}")
private String serverPort;
@Value("${management.port:${server.port}}")
private String managementPort;
@Value("${server.additionalPorts:null}")
private String additionalPorts;
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainer() {
return factory -> {
Connector[] additionalConnectors = additionalConnector();
if (additionalConnectors != null && additionalConnectors.length > 0) {
factory.addAdditionalTomcatConnectors(additionalConnectors);
}
};
}
private Connector[] additionalConnector() {
if (StringUtils.isEmpty(this.additionalPorts)) {
return new Connector[0];
}
Set<String> defaultPorts = Sets.newHashSet(this.serverPort, this.managementPort);
String[] ports = this.additionalPorts.split(",");
List<Connector> result = new ArrayList<>();
for (String port : ports) {
if (StringUtils.hasText(port) && !"null".equalsIgnoreCase(port) && !defaultPorts.contains(port)) {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(Integer.valueOf(port.trim()));
result.add(connector);
}
}
return result.toArray(new Connector[]{});
}
}
アプリケーションの起動時にTomcatServletWebServerFactoryを受け取り、server.additionalPortsというプロパティの値に基づいてTomcatのConnectorを追加しています。
そしてapplication.ymlには以下の値を追加します。
server:
port: 8654
additionalPorts: 30212, 30224
3つのポートでTomcatが移動されたことがログで確認できます。
2019-04-02 15:34:05,816 [INFO ] o.a.c.h.Http11NioProtocol.log - Starting ProtocolHandler ["http-nio-8654"]
2019-04-02 15:34:05,820 [INFO ] o.a.c.h.Http11NioProtocol.log - Starting ProtocolHandler ["http-nio-30212"]
2019-04-02 15:34:05,823 [INFO ] o.a.c.h.Http11NioProtocol.log - Starting ProtocolHandler ["http-nio-30224"]
2019-04-02 15:34:05,825 [INFO ] o.s.b.w.e.t.TomcatWebServer.start - Tomcat started on port(s): 8654 (http) 30212 (http) 30224 (http) with context path ''