从部署到已经运行的Tomcat 8实例{Spring}的Spring Boot WAR文件中获取运行Tomcat的端口

时间:2015-09-17 19:08:15

标签: java spring tomcat spring-boot

我有一个Spring Boot应用程序,其中应用程序的每个实例都是集群中的节点,并且每个节点都需要能够与集群中的其他节点通信以共享信息。出于性能原因,这不可能通过HTTP发生,尽管群集中每个节点的初始联系是通过HTTP调用。

要进行初始HTTP调用,实例需要能够获取正在运行其他实例的端口,以便它们可以相互注册。这意味着每个节点都需要知道其Tomcat实例正在使用的端口。

如果我部署包含嵌入式Tomcat实例的WAR文件,这样可以正常工作。我为EmbeddedServletContainerInitializedEvent注册一个ApplicationListener,并从EmbbededServletContainer获取端口。

当我将WAR文件部署到已经运行的Tomcat实例时出现问题。我无法找到确定运行Tomcat实例的端口的方法,并且由于Tomcat实例已在运行,因此上述事件不再触发。

有人知道如何找出正在使用的端口吗?

3 个答案:

答案 0 :(得分:0)

简单地说:你不能。 webapp并不知道它正在运行的容器。事实上,Tomcat可以有多个连接器并且可以在多个端口中监听......

答案 1 :(得分:0)

我知道这并没有具体回答您的问题,但是有更简单的方法来实现群集节点发现。

作为一个明显的例子,我建议考虑使用共享数据库。这已由JGroups实现为JDBC_PING

答案 2 :(得分:0)

经过一些工作后,以下问题的代码解释了这个问题的解决方法(谢谢Ann Addicks让我再看一遍): org.apache.catalina.ServerFactory.getServer() equivalent in Tomcat 7

此代码对SpringBoot应用程序中调用它的位置非常敏感。由于ApplicationPreparedEvent,我的初始化代码在SpringBoot应用程序启动时很早就运行了。当我第一次尝试这段代码时,我让它运行得如此早以至于代码会失败。我不太清楚为什么,但我不需要提前做这个初始化,所以我在启动时稍稍调用了这段代码并解决了问题。

此代码需要注意以下几点:

  1. 正如joshiste指出的那样,这只会让我找到一个Tomcat端口,但这就是我需要的全部内容。

  2. 正如Alex指出的那样,群集应该由一些后端持久性存储来处理,我已经这样做了。问题在于,有时节点需要调用另一个节点,因为其他节点在集群中具有密切的知识。这是一种不寻常的情况,对整个集群的完整性至关重要。

  3. 以下方法显示了我最终如何使用它:

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