Есть ли способ обеспечить порядок развертывания в 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.
добавлять
Context
элемент внутриHost
элемент в$CATALINA_BASE/conf/server.xml
файл.<Server><Service><Engine><Host> <Context path="[webappName]" docBase="[webappPath]"/> </Server></Service></Engine></Host>
Создать
$CATALINA_BASE/conf/[engineName]/[hostName]/[webappName].xml
файл с содержанием:<Context docBase="[webappPath]"/>
Добавить
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"
Попробуйте следующие шаги:
- Поместите все военные файлы в
$CATALINA_BASE/webapps/
каталог. создать
$CATALINA_BASE/conf/Catalina/localhost/b.xml
файл с содержанием:<Context docBase="b.war"/>
добавлять
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>