是否有办法在tomcat6中强制执行部署顺序?



我有三个战争在我的webapp文件夹。其中两个是建立在第三个的服务之上的。我在一个测试环境中,也就是说,我不能控制他们的架构,所以我不能改变任何事情。所以…

问题:有没有办法在tomcat中强制执行部署顺序?

我在stackoverflow中遇到了一个问题,但是没有解决方案。

嗯,实际上这家伙建议把web应用程序的名字按字母顺序改变会有帮助。但是,我不愿意每次我需要测试这些和不同的战争时都这样做。

我肯定有一种方法可以配置tomcat conf .xml文件之一。我只是不知道是哪一个。

来自Tomcat Wiki - webapps启动的顺序是什么(或者我如何更改启动顺序)?

没有预期的启动顺序。Servlet规范也没有Tomcat定义一个。你不能指望应用程序在任何地方启动特定顺序。

Tomcat有never支持指定webapps的加载顺序。还有其他容器(如JBoss)可以这样做,但是Tomcat没有。任何看起来像通过web应用程序名称的字母顺序加载排序的明显行为都是巧合,并不能保证在所有情况下都有效。

你可能想到的是<load-on-startup/>元素,如果web.xml指定了加载servlets的顺序。

也就是说,有一个使用服务发现协议的优雅解决方案。

一个解决方案是使用像ZeroConf这样的东西,在服务启动时注册你的服务,然后让依赖的应用程序寻找这些服务何时可用,并在服务准备好时让它们连接并做它们需要做的事情。这就是我多年来处理多个依赖服务的方式。我有Python, Java和Erlang服务都可以通过ZeroConf无缝地发现彼此。

tomcat确实没有提供任何强制部署顺序的方法。

*Tomcat按照以下顺序部署webapps:*

1。任何上下文描述符将首先被部署。

2。未被任何上下文描述符引用的已分解的web应用程序将被部署。如果它们在appBase中有一个相关联的。war文件,并且它比被分解的web应用程序更新,那么被分解的目录将被删除,web应用程序将从。war

中重新部署。

3。WAR文件将被部署

>这里是一个建议的解决方案:


如果你想指定部署顺序,那么在$CATALINA_BASE/conf/[engineename]/[hostname]/MyApp.xml中为你的web应用定义一个上下文

Tomcat扫描$CATALINA_BASE/conf/[engineename]/[hostname]/通过执行File listFiles()返回一个按哈希值排序的File数组(依赖于操作系统)。

你可以使用下面的代码来检查webapps的部署顺序

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

为交叉发布道歉(Tomcat -以特定顺序启动webapps),但我认为这也是相关的:

您可以在server.xml中定义多个服务,它们运行在不同的端口上。服务按照它们在server.xml中出现的顺序依次启动。这意味着你可以——例如——在第一个服务中运行一个配置服务,然后在第二个服务中运行依赖于它的应用程序(我使用默认的Catalina…)

你可以在这里看到更多信息:http://wiki.apache.org/tomcat/FAQ/Miscellaneous问

这是我在之前包含的服务

<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,如果你喜欢…

注意,同时更改服务和引擎的名称是很重要的。

HTH

有三种方法可以在Tomcat中部署webapp.war

  1. $CATALINA_BASE/conf/server.xml文件的Host元素中添加Context元素

    <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. 直接在$CATALINA_BASE/webapps/目录下添加webapp.war文件

Tomcat启动时将执行以下部署顺序:

1→2→3


一些解释:

    CATALINA_BASE美元
  • 引用解析大多数相对路径的基目录。如果您没有通过设置CATALINA_BASE目录来为多个实例配置Tomcat,那么$CATALINA_BASE将被设置为$CATALINA_HOME的值,即您已经安装Tomcat的目录。

  • docBase

    web应用程序WAR文件的路径名。您可以为这个WAR文件指定一个绝对路径名,或者一个相对于所属主机的appBase目录的路径名。

  • engineName:

    与上下文关联的引擎的名称。默认名称为Catalina

  • 主机名:

    与上下文关联的主机名。默认名称为localhost


假设:

  • 有3个webapps: a.war, b.warc.war
  • b.war依赖于a.war
  • c.war依赖于b.war
  • Server.Service.Engine.name = "Catalina"
  • Server.Service.Engine.Host.name = "localhost"
  • Server.Service.Engine.Host。appBase = "webapps"

尝试以下步骤:

  1. 把所有的war文件放到$CATALINA_BASE/webapps/目录下。
  2. 创建$CATALINA_BASE/conf/Catalina/localhost/b.xml文件,内容为:

    <Context docBase="b.war"/>
    
  3. $CATALINA_BASE/conf/server.xml文件中添加Context元素:

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

参考:

  • https://tomcat.apache.org/tomcat - 9.0 - doc/deployer howto.html
  • http://tomcat.apache.org/tomcat - 9.0 - doc/config/context.html

始终可以将第一个.war文件移动到tomcat目录中,然后等待它部署,然后将接下来的两个文件移动到tomcat目录中。这将部署第一个,然后部署其他两个。

或者,您可以使用Tomcat扫描目录并按字母顺序部署第一场战争,然后是第二场战争,然后是第三场战争

这很容易实现,如果您不在乎破解Tomcat代码并创建自己的主机实例

1)创建org.apache.catalina.core的子类。标准主机,输入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主机标签()

看起来不可思议,它解决了问题,只要你有所有的web应用程序声明在正确的顺序内的Host标签:

<Host>
 <context app1>
 <context app2>

那么,无论您使用哪种SO, app1都将在app2之前启动。

我们运行多个tomcat。我们可以通过将第一组应用程序放在一个tomcat中,后一组应用程序放在另一个tomcat中来独立地创建应用程序组。

这假设它们没有尝试使用JVM相互通信。

基于@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]);
    }
}

从Maven仓库获取tomcat-catalina-*.jar,并将其编译为DeterministicDeployOrderHost.class:

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

将编译后的.class文件复制到$CATALINA_HOME/lib中,并添加如下内容到主机:

<Host ... className="DeterministicDeployOrderHost">
  <Context .../>
  <Context .../>
</Host>

最新更新