Tomcat-按特定顺序启动Web应用程序
我知道Tomcat和Servlet规范 然而,在我看来,这似乎是一个常见的用例,我想知道是否有人发现了一个聪明的解决方法 我有一个webappa,它使用springremoting来公开一个共享服务,webappb是其中的一个客户端。除非Webapp A正在运行,否则Webapp B无法初始化。然而,我的Tomcat总是以线性方式启动webapp,从webapp B开始 出于基础设施方面的原因,我必须让它们在同一个Tomcat服务器上运行 有什么想法吗 谢谢, 罗伊 更新- 事实证明,在我的特殊情况下,顺序并不重要。原因是:假设我使用以下方法之一在应用程序B之前启动应用程序A。因此应用程序A启动,但是,由于SpringRemoting使用HTTP调用程序,HTTP端口尚未打开(在所有应用程序启动之前它不会打开)。所以A将启动,B将挂起,因为它正在寻找的端口还不可用。DohTomcat-按特定顺序启动Web应用程序,tomcat,servlets,Tomcat,Servlets,我知道Tomcat和Servlet规范 然而,在我看来,这似乎是一个常见的用例,我想知道是否有人发现了一个聪明的解决方法 我有一个webappa,它使用springremoting来公开一个共享服务,webappb是其中的一个客户端。除非Webapp A正在运行,否则Webapp B无法初始化。然而,我的Tomcat总是以线性方式启动webapp,从webapp B开始 出于基础设施方面的原因,我必须让它们在同一个Tomcat服务器上运行 有什么想法吗 谢谢, 罗伊 更新- 事实证明,在我的特殊
最终的结果是两个独立的Tomcat实例。我们有同样的问题,要解决这个问题,我们依赖于这样一个事实(我知道很滑),即应用程序是按照
/conf/server.xml
中定义的顺序启动的
这当然有一个缺点,那就是在
server.xml
中对应用程序进行硬编码,但我们可以接受它。理论上,您可以通过contextInitialized()
中的ExecutorService
生成一个Runnable
,然后每隔一定时间检查另一个webapp的可用性(可能通过触发HTTPHEAD
请求?)。一旦另一个Web应用可用,然后在servlet上下文中设置一些属性,这表明。添加一个过滤器,检查该属性的存在,并相应地阻止/继续请求。我使用了一个很好的技巧来创建两个级别的Web应用加载。在每个级别中,顺序都不保证。这依赖于tomcat将首先从tomcat/conf/[Engine Name]/[Host Name]加载上下文描述符,然后才从server.xml中Host元素的appBase属性加载上下文
只需将以下代码添加到您希望在第二级(即稍后)加载的webapp中
如果你不在乎破解一点tomcat代码和创建你自己的主机实例,这是很容易实现的
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主机标记()上注册类
尽管看起来不可思议,但只要您在主机标签中以正确的顺序声明所有web应用,它就能解决问题:
<Host>
<context app1>
<context app2>
</Host>
Thaen app1将在app2之前启动,无论您使用哪种方式 我知道这个问题有点老了,但我在尝试做同样的事情时发现了它,并认为我应该更新一个更好的解决方案
您可以在server.xml中定义在不同端口上运行的多个服务。这些服务按照它们在server.xml中的显示顺序依次启动。这意味着您可以在第一个服务中运行一个配置服务,然后在第二个服务中运行依赖它的应用程序(我使用默认的Catalina服务用于其余服务…)
您可以在此处查看更多信息:
这是我在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
注意:更改服务和引擎的名称很重要
HTH这里是Linux上的另一个技巧
由于错误的WSDL,我们的一些webservice应用程序无法部署。如果在许多其他应用程序之后部署或启动它们,就会发生这种情况。
它们的启动顺序取决于在/opt/apache-tomee/conf/Catalina/localhost中找到上下文xml的顺序
可以使用“ls-1f
”进行验证。一个普通的“ls”给出一个排序的输出
这过去是文件添加到该目录的顺序,但对于ext4文件系统,该顺序基于文件名的散列。可以按如下方式禁用此功能:
# tune2fs -O ^dir_index /dev/xyz
现在你至少可以自己决定它们的启动顺序。重新排序:将所有文件移到临时文件夹,按所需顺序将其移回。旧线程,但
解决此问题的另一种方法是创建一个自定义HostConfig类,该类按您需要的方式对web应用进行排序
public class OrderedHostConfig extends HostConfig {
@Override
protected String[] filterAppPaths(String[] unfilteredAppPaths) {
String[] files = super.filterAppPaths(unfilteredAppPaths);
Arrays.sort(files, compare());
return files;
}
private Comparator<String> compare() {
return (o1, o2) -> {
// Your own implementation
};
}
}
公共类OrderedHostConfig扩展了HostConfig{
@凌驾
受保护的字符串[]筛选器应用路径(字符串[]未筛选的应用路径){
String[]files=super.filterapppath(未筛选的应用路径);
sort(文件,compare());
归还文件;
}
专用比较器compare(){
返回(o1,o2)->{
//您自己的实现
};
}
}
然后可以在主机定义下的server.xml中引用此类
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" hostConfigClass="your.package.OrderedHostConfig">
您需要将其编译成jar并保存在Tomcat的/lib目录中。就我而言:
/var/lib/tomcat8/lib
我喜欢这种方法,因为:
该命令仅在相关的地方强制执行,但不需要使用上下文在主机定义中手动管理所有WebApp
在代码库中搜索.war文件名也将引用该类,这使得在重命名文件时更容易找到该类
不更改tomcat 8的私有最终字段,请参阅
由于没有一个选项适用于Tomcat 9.0.19(也就是@Luiz提到的选项),我们使用了代码方法,用最少的自定义实现替换了Tomcat StandardHost和HostConfig:
public class CustomTomcatHost extends StandardHost {
public CustomTomcatHost() {
super();
}
@Override
public void addLifecycleListener(LifecycleListener listener) {
if (listener instanceof HostConfig) {
listener = new OrderedHostConfig();
}
super.addLifecycleListener(listener);
}
}
必须覆盖HostConfig中的deployApps函数,以便进行排序
public class CustomTomcatHost extends StandardHost {
public CustomTomcatHost() {
super();
}
@Override
public void addLifecycleListener(LifecycleListener listener) {
if (listener instanceof HostConfig) {
listener = new OrderedHostConfig();
}
super.addLifecycleListener(listener);
}
}
public class OrderedHostConfig extends HostConfig {
public OrderedHostConfig() {
super();
}
public String[] prioritySort(String[] paths) {
if (paths == null) return null;
Arrays.sort(paths, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b); //TODO: sort paths based on your criteria
}
});
return paths;
}
@Override
protected void deployApps() {
File appBase = host.getAppBaseFile();
File configBase = host.getConfigBaseFile();
String[] apps = prioritySort(filterAppPaths(appBase.list()));
// Deploy XML descriptors from configBase
deployDescriptors(configBase, prioritySort(configBase.list()));
// Deploy WARs
deployWARs(appBase, apps);
// Deploy expanded folders
deployDirectories(appBase, apps);
}
}
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" className="com.example.CustomTomcatHost" >