简体   繁体   中英

Obtaining the port that Tomcat is running on from inside a Spring Boot WAR file deployed to an already running instance of Tomcat 8

I have a Spring Boot application where each instance of the application is a node in a cluster, and each node needs to be able to talk to the other nodes in the cluster to share information. For performance reasons, this cannot happen via HTTP, although the initial contact for each node in the cluster is via an HTTP call.

To make the initial HTTP call, instances need to be able to obtain the port that the other instances are running on so that they can register with each other. This means that each node needs to know what port its Tomcat instance is using.

This works fine if I deploy a WAR file that contains an embedded Tomcat instance. I register an ApplicationListener for the EmbeddedServletContainerInitializedEvent and get the port from the EmbbededServletContainer.

The problem comes when I deploy the WAR file to an already running Tomcat instance. I am unable to find a way to determine what port that Tomcat instance is running on, and the aforementioned event does not fire anymore as the Tomcat instance is already running.

Anyone got any ideas on how to find out what port is being used?

Simply: you can't. The webapp doesn't know the container it is running in. In fact a Tomcat could have multiple connectors and be listening in multiple ports...

I know this doesn't answer your question specifically, however there are much easier ways of implementing cluster node discovery.

As an obvious example I would recommend looking into using the shared database. This has been implemented by JGroups as JDBC_PING .

After some work, the fix to this issue is explained in the code in the following question (thank you Ann Addicks for making me look at it again): org.apache.catalina.ServerFactory.getServer() equivalent in Tomcat 7

This code is very sensitive to where it gets called in a SpringBoot application. My initialization code runs very early in the startup of the SpringBoot application, as a result of the ApplicationPreparedEvent. When I first tried this code, I had it running so early that the code would fail. I'm not quite sure why, but I didn't need to do this initialization that early, so I moved the call to this code a little later in my startup and it solved the problem.

There are a couple of caveats to this code to be aware of:

  1. As joshiste pointed out, this only gets me one of the Tomcat ports, but that's all that I need in my case.

  2. As Alex pointed out, clustering should really be handled by some back-end persistence store, and I am already doing that. The issue is that there are times where one node needs to call another node because of intimate knowledge the other node has in the cluster. It's an unusual situation that is critical to the integrity of the overall cluster.

The following method shows how I finally got this to work:

private int getTomcatContainerPort() throws MalformedObjectNameException, AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException {
    int serverPort = 0;
    MBeanServer mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
    ObjectName name = new ObjectName("Catalina", "type", "Server");
    Server server = (Server) mBeanServer.getAttribute(name, "managedResource");
    Service[] services = server.findServices();
    for (Service service : services) {
        for (Connector connector : service.findConnectors()) {
            ProtocolHandler protocolHandler = connector.getProtocolHandler();
            if (protocolHandler instanceof Http11Protocol
                || protocolHandler instanceof Http11AprProtocol
                || protocolHandler instanceof Http11NioProtocol) {
                serverPort = connector.getPort();
                break;
            }
        }
    }
    return serverPort;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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