2010-10-05 2 views
27

Есть ли какой-либо доступный API или конфигурация Tomcat, который может сообщать приложение (возможно, при запуске), какой порт работает без запроса?Получить номер порта сервера от tomcat без запроса

Представьте себе сценарий, в котором есть два веб-приложения, работающие в одном Tomcat, и один из них требует вызова веб-службы из другого. Мы не хотим, чтобы запрос оставил Tomcat (если вы используете имя сервера Apache или абсолютный URL-адрес, запрос выйдет и вернется снова, и он может перейти в любой экземпляр) и вернуться. Для этого я знаю, имя машины, но не способ получить номер порта. Я знаю, что могу жестко закодировать эту информацию, но я не хочу этого делать, поскольку я хочу, чтобы мой файл war был агностиком сервера приложений.

Я знаю, что мы можем найти его, если у нас есть HTTPServletRequest

Это работает только для Tomcat 6 и не будет работать на Tomcat 7

+0

Я не уверен, почему приложение должно знать abo порт. Можете ли вы предоставить дополнительные сведения о том, зачем вам это нужно? – David

+1

Вы хотите все доступные порты или определенный порт? Сервер приложений может прослушивать многие порты (например, порт http 80 и https-порт 443). – Codemwnci

+0

@Codemwnci - Да, если я могу .. –

ответ

20

Для всех, кто заинтересован в том, как мы решили эту проблему, вот фиктивный код

Server server = ServerFactory.getServer(); 
     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(); 
        System.out.println("HTTP Port: " + connector.getPort()); 
       } 
      } 


     } 
+0

Спасибо за этот код - похоже, нигде не найти! – woolyninja

+8

Не работает на tomcat-7 - см. Http://stackoverflow.com/questions/6833947/org-apache-catalina-serverfactory-getserver-equivalent-in-tomcat-7 –

+0

ни на jboss, как 7 = \ – thiagoh

-1

Хм, как бы приложение начать работу в Tomcat без запроса ? Может быть, я сейчас нахожу мозг мертвым, но я не думаю, что какие-либо классы будут загружаться до тех пор, пока не ударит запрос. Конечно, у вас могут быть классы, не зависящие от какого-либо конкретного запроса, но им нужен запрос, чтобы их уволить в какой-то момент.

+1

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

0

Я не совсем уверен, что вы можете получить доступ к порту Tomcat из кода в конфигурации среды, в которой вы нуждаетесь. Считаете ли вы, что на самом деле полный URL-адрес веб-службы передан в качестве параметра конфигурации/параметра (возможно, в файле .properties) для приложения?

Таким образом, вам не нужно будет жестко кодировать порт и отключать оба приложения, чтобы вы могли технически иметь веб-службу на внешнем tomcat, но все же получить к ней доступ, просто изменив свойство, избегая повторной сборки кода ,

+0

Да, мы действительно это рассмотрели, но проблема в том, что каждая машина имеет более одного экземпляра tomcat (может быть, это более сложно?) И, очевидно, они работают на разных портах. Таким образом, порт не может быть жестко закодирован. –

+0

Вы говорите, что веб-сервис (URL-адрес и порт) перемещается так часто, что передача его через настройку не будет работать? Если это так, похоже, что существует проблема с архитектурой. Если нет, то передавать его через настройки обычно не сложно, если мы знаем (вручную), где находится веб-служба (URL + порт)? – Sarat

+0

В кластере может быть количество экземпляров tomcat, и моя цель - перенаправить запрос из одного приложения в другое приложение, которое должно перейти к тому же экземпляру tomcat, а не к случайному экземпляру tomcat. –

1

Вы можете использовать crossContext. Но я не думаю, что это сервер приложений агностик.

Я бы поделился пользовательским классом, ведя себя как реестр запущенных приложений в том же экземпляре tomcat через JNDI, как я объяснил here.

При запуске через ContextListener или через событие контейнера Spring я получаю реестр с помощью поиска JNDI, добавляю экземпляр веб-приложения с URL-адресом, полученным из файла servletcontext.contextpath, и, наконец, регистрирую слушателя, чтобы слышать другие регистрации приложений. Это больше агностик сервера, о котором я могу думать.

Получение порта не будет агротическим агентом, вы должны использовать параметр контекста.

EDIT: Извините, я забыл сказать, что то, что я описал, заключается в том, чтобы обмениваться объектами между контекстами, но нет, вы не можете знать порт, если не используете какой-либо серверный API (не агностик вообще) ,

0

Раньше в крупном распределенном проекте я использовал централизованный сервис, который инициализировал несколько сервисов с URL-адресом центральной службы (&).

Очевидно, что это означает, что центральная служба должна поддерживать список услуг (URL-адрес & порт) для инициализации.

1

Номер порта сервера не существует. Он может иметь любое количество номеров портов. То, что вы просите, не имеет смысла.Номер, связанный с конкретным запросом делает имеет смысл.

+0

@downvoter Пожалуйста, объясните. У меня есть производство Tomcats, использующее по пять портов. Что именно означает * номер порта сервера * в таком контексте? – EJP

1
  • разжиться MBean/JMX объекта для Tomcat/Server Instance
  • Получить Virtual Server Instance связанных данные оттуда

Проверка http://svn-mirror.glassfish.org/glassfish-svn/tags/embedded-gfv3-prelude-b07/web/web-glue/src/main/java/com/sun/enterprise/web/WebContainer.java для справки

Содержание в MBeanServer может затем подвергаются через различные протоколы, реализованные с помощью протокольных соединителей [RMI/IIOP] или протокольных адаптеров [SNMP/HTTP]. В этом случае использование SNMP-адаптера будет лучшим подходом, так что можно разместить ловушку SNMP без знания точного IP-порта других серверов приложений

0

Если вы хотите получить доступ к приложению на том же экземпляре сервера , просто опустите серверную часть URL-адреса. Некоторые примеры, что вы можете достичь. В настоящее время документ находится на http://example.com:8080/app2/doc.html

  • xxx.html становится http://example.com:8080/app2/xxx.html
  • ../xxx.html становится http://example.com:8080/xxx.html
  • ../xxx.html становится http://example.com:8080/xxx.html
  • ../foo/xxx.html становится http://example.com:8080/foo/xxx.html
  • ../../xxx.html становится http://example.com:8080/xxx.html (нет никакого способа, чтобы выйти за пределы корня)
  • /xxx.html становится http://example.com:8080/xxx.htmlВозможно, это то, что вы ищете.
  • //other.com/xxx.html становится http://example.com:8080/xxx.html Полезно, если вы хотите сохранить «https:»
+0

Но вопрос об обнаружении порта слушателя. –

+1

Нет, вопрос в том, как получить доступ к другому приложению на том же сервере. –

+0

-1 Тея сказал: «Я знаю, что мы можем найти его, если у нас есть HTTPServletRequest», и ваш ответ подразумевает входящий запрос. – mschonaker

1

Этих типов серверов предназначены, чтобы иметь возможность слушать (почти) произвольные порты и, чтобы скрыть эти данные от содержащихся приложений, обычно не нужно знать.

Единственный способ - прочитать конфигурационные файлы самостоятельно и имеют доступ к аргументам командной строки, которые запустили сервер, где файлы конфигурации, возможно, были переопределены. Вы должны много узнать о системе, в которой вы работаете, чтобы это работало. Нет способа сделать это портативно.

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

23

С этим:

List<String> getEndPoints() throws MalformedObjectNameException, 
     NullPointerException, UnknownHostException, AttributeNotFoundException, 
     InstanceNotFoundException, MBeanException, ReflectionException { 
    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
    QueryExp subQuery1 = Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")); 
    QueryExp subQuery2 = Query.anySubString(Query.attr("protocol"), Query.value("Http11")); 
    QueryExp query = Query.or(subQuery1, subQuery2); 
    Set<ObjectName> objs = mbs.queryNames(new ObjectName("*:type=Connector,*"), query); 
    String hostname = InetAddress.getLocalHost().getHostName(); 
    InetAddress[] addresses = InetAddress.getAllByName(hostname); 
    ArrayList<String> endPoints = new ArrayList<String>(); 
    for (Iterator<ObjectName> i = objs.iterator(); i.hasNext();) { 
     ObjectName obj = i.next(); 
     String scheme = mbs.getAttribute(obj, "scheme").toString(); 
     String port = obj.getKeyProperty("port"); 
     for (InetAddress addr : addresses) { 
      if (addr.isAnyLocalAddress() || addr.isLoopbackAddress() || 
       addr.isMulticastAddress()) { 
       continue; 
      } 
      String host = addr.getHostAddress(); 
      String ep = scheme + "://" + host + ":" + port; 
      endPoints.add(ep); 
     } 
    } 
    return endPoints; 
} 

Вы получите список, как это:

[http://192.168.1.22:8080] 
2
public void getIpAddressAndPort() 
throws MalformedObjectNameException, NullPointerException, 
      UnknownHostException { 

     MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer(); 

     Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"), 
       Query.match(Query.attr("protocol"), Query.value("HTTP/1.1"))); 

     String host = InetAddress.getLocalHost().getHostAddress(); 
     String port = objectNames.iterator().next().getKeyProperty("port"); 

     System.out.println("IP Address of System : "+host); 
     System.out.println("port of tomcat server : "+port); 

    } 
+1

Хотя этот код может ответить на вопрос, предоставляя дополнительный контекст относительно * how * и/или * почему *, он решает проблему, улучшит долгосрочную ценность ответа. - [Из обзора] (http://stackoverflow.com/review/low-quality-posts/13317054) –