Есть ли способ обеспечить порядок развертывания в tomcat6?

У меня есть 3 войны в моей папке веб-приложения. Два из них построены на услугах третьего. Я нахожусь в среде тестирования, то есть я не контролирую их архитектуру, поэтому я ничего не могу изменить. Так...

Вопрос: Есть ли способ применить порядок развертывания в tomcat?

Я столкнулся с одним вопросом здесь в stackru, но нет никакого решения.

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

Я уверен, что есть способ сделать это, настроив один из файлов tomcat conf .xml. Я просто не знаю, какой.

8 ответов

Решение

Из Tomcat Wiki - В каком порядке запускаются веб-приложения (или Как я могу изменить порядок запуска)?

Ожидаемого порядка запуска нет. Ни спецификация сервлета, ни Tomcat не определяют его. Вы не можете полагаться на приложения, запускающиеся в определенном порядке.

Tomcat никогда не поддерживал указание порядка загрузки веб-приложений. Есть и другие контейнеры, такие как JBoss, но Tomcat никогда не делает. Любое очевидное поведение, которое выглядит как упорядочение загрузки через алфавитный порядок имен веб-приложений, является случайным и не гарантируется, что оно будет работать во всех случаях.

То, о чем вы, вероятно, думаете, это <load-on-startup/> элемент, если web.xml который определяет порядок загрузки servlets,

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

Одно из решений состоит в том, чтобы использовать что-то вроде ZeroConf и регистрировать ваши службы при запуске, а затем заставлять зависимые приложения искать, когда эти службы станут доступными, подключать их и делать то, что им нужно, когда служба будет готова. Так я работаю с несколькими зависимыми службами уже много лет. У меня есть службы Python, Java и Erlang, которые все обнаруживают друг друга через ZeroConf.

Это правда, что Tomcat не предоставляет никакого способа обеспечения порядка развертывания.

*Tomcat развертывает веб-приложения в следующем порядке:*

1. Любые контекстные дескрипторы будут развернуты первыми.

2. Затем будут развернуты взорванные веб-приложения, на которые не ссылается ни один дескриптор контекста. Если у них есть связанный файл.WAR в appBase, и он новее, чем разорванное веб-приложение, разорванный каталог будет удален, а веб-приложение будет повторно развернуто из.WAR.

3.WAR файлы будут развернуты

> Вот предлагаемое решение:


Если вы хотите указать порядок развертывания, определите контекст для вашего веб-приложения в $CATALINA_BASE/conf/[enginename]/[hostname] /MyApp.xml

Tomcat сканирует $CATALINA_BASE/conf/[enginename]/[имя хоста] /, выполняя File listFiles(), которая возвращает массив файлов, отсортированный по значению хеша (зависит от ОС).

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

File file = new File("/opt/tomcat/conf/Catalina/localhost");
        File[] files = file.listFiles();
        for (File f : files)
        {
            System.out.println("Filename: " + f.getName());
        }

Есть три способа развернуть webapp.war в Tomcat.

  1. добавлять Context элемент внутри Host элемент в $CATALINA_BASE/conf/server.xml файл.

    <Server><Service><Engine><Host>
        <Context path="[webappName]" docBase="[webappPath]"/>
    </Server></Service></Engine></Host>
    
  2. Создать $CATALINA_BASE/conf/[engineName]/[hostName]/[webappName].xml файл с содержанием:

    <Context docBase="[webappPath]"/>
    
  3. Добавить webapp.war файл прямо в $CATALINA_BASE/webapps/ каталог.

Следующая последовательность развертывания произойдет при запуске Tomcat:

1 → 2 → 3


Некоторые объяснения:

  • $CATALINA_BASE

    Обратитесь к базовому каталогу, в котором разрешены большинство относительных путей. Если вы не настроили Tomcat для нескольких экземпляров, установив каталог CATALINA_BASE, то для $CATALINA_BASE будет установлено значение $CATALINA_HOME, каталога, в который вы установили Tomcat.

  • docBase

    Путь к файлу WAR веб-приложения. Вы можете указать абсолютный путь к этому файлу WAR или путь относительно каталога appBase хоста-владельца.

  • engineName:

    Имя движка, связанного с контекстом. Имя по умолчанию Catalina,

  • Hostname:

    Имя хоста, связанного с контекстом. Имя по умолчанию localhost,


Предположим, что:

  • Есть 3 веб-приложения: a.war, b.war а также c.war,
  • b.war зависит от a.war,
  • c.war зависит от b.war,
  • Server.Service.Engine.name = "Каталина"
  • Server.Service.Engine.Host.name = "localhost"
  • Server.Service.Engine.Host.appBase = "webapps"

Попробуйте следующие шаги:

  1. Поместите все военные файлы в $CATALINA_BASE/webapps/ каталог.
  2. создать $CATALINA_BASE/conf/Catalina/localhost/b.xml файл с содержанием:

    <Context docBase="b.war"/>
    
  3. добавлять Context элемент в $CATALINA_BASE/conf/server.xml файл:

    <Server><Service><Engine><Host>
        <Context path="a" docBase="a.war"/>
    </Server></Service></Engine></Host>
    

Ссылка:

Извиняюсь за перекрестную публикацию ( Tomcat - запуск веб-приложений в определенном порядке), но я подумал, что это также актуально и здесь:

Вы можете определить несколько сервисов в вашем server.xml, которые работают на разных портах. Сервисы запускаются последовательно в порядке их появления в server.xml. Это означает, что у вас может быть, например, служба конфигурации, работающая в первой службе, а затем приложения, которые зависят от нее, во второй (для остальных я использую одну по умолчанию Catalina...)

Вы можете увидеть больше информации здесь: http://wiki.apache.org/tomcat/FAQ/Miscellaneous

И это сервис, который я включаю перед службой Catalina:

<Service name="ConfigService">
    <Connector port="8081" protocol="HTTP/1.1"
        connectionTimeout="20000"
        redirectPort="8444" />
    <Engine name="ConfigServiceEngine" defaultHost="localhost">
        <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true"
            xmlValidation="false" xmlNamespaceAware="false">

            <Context path="/" reloadable="true" docBase="/path/to/your/service/directory" />
        </Host>
    </Engine>
</Service>

Как вы можете видеть, я использую docbase, а не appBase, но вы сможете настроить другую appBase, если хотите...

Внимание: важно изменить название службы и двигателя.

НТН

Вы всегда можете переместить первый.war-файл в каталог tomcat, затем дождаться его развертывания, а затем переместить следующие два в каталог tomcat. Это развернет первый, а затем развернет два других.

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

Мы запускаем несколько котов. Мы можем вызывать группы приложений независимо друг от друга, поместив первую группу в одного кота, а последующие в секунду.

Это предполагает, что они не пытаются общаться друг с другом с помощью JVM.

Этого довольно легко достичь, если вам все равно, взломать код tomcat и создать свой собственный экземпляр Host

1) Создайте подкласс org.apache.catalina.core.StandardHost, скажем, MyHost:

class MyHost extends org.apache.catalina.core.StandardHost{
    public MyHost (){
    super();
    //changing HashMap for a predictable ordered Map :)
    this.children = new LinkedHashMap();
    }
} 

2) зарегистрируйте свой класс в теге xml Host вашего сервера ()

Невероятно, но это решает проблему до тех пор, пока все ваше веб-приложение объявлено в правильном порядке внутри тега Host:

<Host>
 <context app1>
 <context app2>

Thaen app1 запустится до app2, независимо от того, какой SO вы использовали.

Основываясь на ответе @Luiz для Tomcat 9 (в которомchildrenтеперь окончательный), нам пришлось переопределить несколько методов, скопировав в некоторых случаях базовую функциональность.

Это ни для чего не оптимизировано, но загружает контексты в том порядке, в котором они определены в вашемserver.xml.

      // DeterministicDeployOrderHost.java

import java.lang.Override;
import java.lang.String;
import java.util.LinkedHashSet;
import javax.management.ObjectName;
import org.apache.catalina.Container;

public class DeterministicDeployOrderHost extends org.apache.catalina.core.StandardHost {
    private final LinkedHashSet<String> childrenOrder = new LinkedHashSet<>();

    @Override
    public void addChild(Container container) {
        synchronized (children) {
            super.addChild(container);
            childrenOrder.add(container.getName());
        }
    }

    @Override
    public void removeChild(Container container) {
        synchronized (children) {
            super.removeChild(container);
            childrenOrder.remove(container.getName());
        }
    }

    @Override
    public Container[] findChildren() {
        synchronized (children) {
            var list = new java.util.ArrayList<Container>(children.size());
            for (var childName : childrenOrder) {
                list.add(children.get(childName));
            }
            return list.toArray(new Container[0]);
        }
    }

    @Override
    public ObjectName[] getChildren() {
        var names = new java.util.ArrayList<ObjectName>(children.size());
        for (var childName : childrenOrder) {
            var next = children.get(childName);
            if (next instanceof org.apache.catalina.core.ContainerBase) {
                names.add(next.getObjectName());
            }
        }
        return names.toArray(new ObjectName[0]);
    }
}

Получите tomcat-catalina-*.jar, например, из репозитория Maven и скомпилируйте его вDeterministicDeployOrderHost.class:

      javac DeterministicDeployOrderHost.java -cp tomcat-catalina-9.0.65.jar

Затем скопируйте скомпилированный.classфайл в$CATALINA_HOME/libи добавьте следующее к хосту:

      <Host ... className="DeterministicDeployOrderHost">
  <Context .../>
  <Context .../>
</Host>
Другие вопросы по тегам