2015-09-17 1 views
1

У меня есть приложение Spring Boot, в котором каждый экземпляр приложения является узлом в кластере, и каждый узел нуждается в чтобы иметь возможность разговаривать с другими узлами в кластере для обмена информацией. По соображениям производительности это не может произойти через HTTP, хотя начальный контакт для каждого узла в кластере осуществляется через HTTP-вызов.Получение порта, который Tomcat запускается из файла WAR WAR Spring, развернутого в уже запущенном экземпляре Tomcat 8

Чтобы выполнить начальный HTTP-вызов, экземпляры должны иметь возможность получить порт, в котором работают другие экземпляры, чтобы они могли регистрироваться друг с другом. Это означает, что каждый узел должен знать, какой порт использует его экземпляр Tomcat.

Это прекрасно работает, если я развожу WAR-файл, содержащий встроенный экземпляр Tomcat. Я регистрирую ApplicationListener для EmbeddedServletContainerInitializedEvent и получаю порт из EmbbededServletContainer.

Проблема возникает при развертывании WAR-файла в уже запущенном экземпляре Tomcat. Я не могу найти способ определить, какой порт используется для экземпляра Tomcat, и вышеупомянутое событие больше не срабатывает, поскольку экземпляр Tomcat уже запущен.

У кого-нибудь есть идеи, как узнать, какой порт используется?

+0

Вы пробовали что-нибудь еще? Вот сообщение для tomcat7 http://stackoverflow.com/questions/6833947/org-apache-catalina-serverfactory-getserver-equivalent-in-tomcat-7 вы его видели? –

+0

Привет, Энн. Спасибо за ответ. Я нашел ответ, на который вы ссылались некоторое время назад, но это не помогло мне в этот момент. После прочтения вашего вопроса я пошел и попробовал его снова, и обнаружил, что упомянутый код чувствителен к тому, когда он вызван. Мой код работает до того, как код SpringBoot даже завершил инициализацию. Я теперь нашел, чтобы сделать эту работу, и это решает мою проблему. –

ответ

0

После некоторой работы, исправление к этой проблеме объясняется в коде в следующий вопрос (спасибо Ann Addicks заставила меня взглянуть на него еще раз): org.apache.catalina.ServerFactory.getServer() equivalent in Tomcat 7

Этот код очень чувствителен, где он получает вызванный в приложении SpringBoot. Мой код инициализации запускается очень рано при запуске приложения SpringBoot в результате применения ApplicationPreparedEvent. Когда я впервые пробовал этот код, у меня это работало так рано, что код не сработает. Я не совсем понимаю, почему, но мне не нужно было делать эту инициализацию раньше, поэтому я перевел вызов этого кода чуть позже в мой стартап, и он решил проблему.

Есть несколько предостережений на этот код, чтобы быть в курсе:

  1. Как joshiste отметил, это только получает мне один из портов Tomcat, но это все, что мне нужно в моем случае.

  2. Как указано в Alex, кластеризация должна выполняться с помощью некоторого хранилища постоянных хранилищ, и я уже это делаю. Проблема в том, что бывают случаи, когда один узел должен вызывать другой узел из-за интимного знания, которое имеет другой узел в кластере. Это необычная ситуация, которая имеет решающее значение для целостности общего кластера.

Следующий метод показывает, как я наконец получил эту работу:

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

Просто: вы не можете. Webapp не знает контейнер, в котором он работает. Фактически Tomcat может иметь несколько разъемов и прослушивать несколько портов ...

+0

Спасибо. Да. Это именно тот ответ, который я ожидал. Как я сказал в одном из моих других ответов, я пытаюсь выяснить, возможно ли это. У нас есть рабочее решение с развертыванием с использованием встроенного контейнера Tomcat. В этом случае, однако, мы развертываем в AWS с использованием Elastic Beanstalk и Docker за балансировщиком нагрузки, и мне приходится обрабатывать обнаружение в AWS с использованием API описания и тегов на машинных экземплярах. Я просто пытаюсь определить, возможно ли это. Ваш ответ, кажется, подтверждает то, что я думал. –

0

Я знаю, что это не отвечает на ваш вопрос конкретно, однако есть намного проще способы реализации обнаружения узлов кластера.

В качестве очевидного примера я бы рекомендовал изучить использование общей базы данных. Это было реализовано JGroups как JDBC_PING.

+0

Привет, Алекс, спасибо за совет. Наш общий уровень сохранности уже представляет собой комбинацию Hazelcast, Cassandra/DynamoDB. Это развертывание не является проблемой со встроенными экземплярами Tomcat, но это проблема, когда мы используем комбинацию Elastic Beanstalk, Docker и Tomcat (unembedded). На этом этапе я пытаюсь установить, буду ли я тратить свое время на то, чтобы решить эту проблему, и нам нужно просто дернуть докеры и неподтвержденный Tomcat, так как приложение отлично работает без него. –

Смежные вопросы