Tomcat - 以特定顺序启动 Web 应用程序
我知道 Tomcat 和 Servlet 规范 不支持在特定的环境下启动 webapp订单。
然而,在我看来,这似乎是一个常见的用例,我想知道是否有人找到了一个聪明的解决方法。
我有 webapp A,它使用 Spring Remoting 公开共享服务,webapp B 是其中的客户端。除非 web 应用程序 A 正在运行,否则 Web 应用程序 B 无法初始化。然而,我的 Tomcat 总是从 webapp B 开始线性启动 web 应用程序。
出于基础设施的原因,我必须让它们在同一个 Tomcat 服务器上运行。
有什么想法吗?
谢谢, Roy
更新 -
事实证明,在我的特殊情况下,顺序并不重要。原因是这样的:假设我使用下面的方法之一在应用程序 B 之前启动应用程序 A。因此应用程序 A 启动,但是,由于 Spring 远程处理正在使用 HTTP 调用程序,因此 HTTP 端口尚未打开(它不会打开)直到所有应用程序启动)。因此 A 将启动,而 B 将挂起,因为它正在寻找的端口尚不可用。哦。
最终结果是两个独立的 Tomcat 实例。
I know that Tomcat and the Servlet spec do not support starting webapps in a particular order.
However, this seems to me like a common use case, and I'm wondering if someone has discovered a clever workaround for it.
I have webapp A which uses Spring Remoting to expose a shared service, of which webapp B is a client. Webapp B cannot initialize unless webapp A is running. However, my Tomcat is always starting the webapps linearly, starting with webapp B.
For infrastructure reasons I have to have these running on the same Tomcat server.
Any ideas?
Thanks,
Roy
UPDATE -
Turns out that in my particular case, order doesn't matter. The reason is this: say I use one of the methods below to start app A before app B. So app A starts, but, since Spring remoting is using the HTTP Invoker, the HTTP port is not yet open (it won't open until all apps are started). So A will start, and B will hang, because the port it's looking for is not yet available. Doh.
End result was two separate Tomcat instances.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
难道他们是按照部署的顺序开始的吗?
因此,如果我有四个应用程序:1、2、3、4,并且我按以下顺序部署它们:1、2、4(重新启动 tomcat)、3(重新启动)。它会在某个地方缓存一些东西以使项目始终按该顺序启动吗?所以1、2、4、3。它发生在这里。我不确定,但也许它对某人有帮助。
Can it be that they are starting in the order as they are deployed in?
So if i have four apps: 1, 2, 3, 4 and i deploy them in the following order: 1, 2, 4 (restart tomcat), 3 (restart). That it caches something somewhere to make the projects always startup in that order? So 1, 2, 4, 3. It happens over here. I'm unsure, but maybe it helps someone.
我们有同样的问题,为了解决这个问题,我们依赖于这样一个事实(我知道这很滑稽):应用程序按照它们在
/conf/server.xml
中定义的顺序启动。 。当然,这在
server.xml
中硬编码应用程序有一个缺点,但我们可以忍受它。We have the same problem and to solve it we're relying on the fact (slippery, I know) that applications are started in the order they are defined in
<tomcat_home>/conf/server.xml
.This of course has a disadvantage of hardcoding apps in the
server.xml
but we can live with it.如果您不介意修改一些 tomcat 代码并创建自己的 Host 实例,那么这很容易实现:
1) 创建 org.apache.catalina.core.StandardHost 的子类,例如 MyHost:
2) 在服务器上注册您的类xml Host tag ()
看起来令人难以置信,只要您在 Host 标记内以正确的顺序声明所有 Web 应用程序,它就可以解决问题:
Thaen app1 将在 app2 之前启动,无论如何你用过哪个SO。
That's quite easy to achieve if you don't care hacking a bit of tomcat code and creating your own Host instance
1) Create a subClass of org.apache.catalina.core.StandardHost, say MyHost:
2) register your class on your server's xml Host tag ()
Incredible as it may seem, it solves the problem as long as you have all your web app declared in the correct order inside of Host tag:
Thaen app1 will start before app2, no matter which SO you used.
这是 Linux 上的另一个技巧。
由于 WSDL 错误,我们的一些 Web 服务应用程序无法部署。如果它们在许多其他应用程序之后部署或启动,就会发生这种情况。
它们的启动顺序取决于在 /opt/apache-tomee/conf/Catalina/localhost 中找到上下文 xml 的顺序
。可以使用“
ls -1f
”进行验证。简单的“ls”给出排序的输出。这曾经是文件添加到该目录的顺序,但对于 ext4 文件系统,该顺序基于文件名的哈希值。可以按如下方式禁用此功能:
现在您至少可以自己决定它们的启动顺序。重新排序:将所有文件移至临时文件夹,然后按所需顺序移回。
Here is another trick on Linux.
Some of our webservice applications fail to deploy, because of erroneous WSDL. This happens if they are deployed or started after a number of other applications.
The order in which they are started depends on the order in which context xml's are found in /opt/apache-tomee/conf/Catalina/localhost
Can be verified using "
ls -1f
". A plain "ls" gives a sorted output.This used to be the order in which files were added to that directory, but with ext4 filesystems, the order is based on a hash of the filename. This can be disabled as follows:
Now you can at least decide yourself in which order they will be started. Reordering: move all files to a temporary folder, move them back in the desired sequence.
旧线程,但是...
解决此问题的另一种方法是创建一个自定义 HostConfig 类,该类根据您需要的方式对 Web 应用程序进行排序。
然后,您可以在 Host 定义下的 server.xml 中引用此类。
您需要将其编译成 jar 并将其保存在 Tomcat 的 /lib 目录中。就我而言:
我喜欢这种方法,因为:
仅在相关的地方强制执行该顺序,但无需使用上下文在主机定义中手动管理所有 webapp
在代码库中搜索 .war 文件名也会引用此类,这使得更容易查找该文件是否为
不更改 tomcat 8 的私有最终字段,请参阅此处< /a>
Old thread, but...
Another way to work around this is to create a custom HostConfig class which sorts the web apps the way you need.
Then you can reference this class in your server.xml under the Host definition.
You need to compile this into a jar and save it in Tomcat's /lib directory. In my case:
I like this method because:
The order is enforced only where it's relevant, but there is no need to manage all the webapps manually in Host definitions using Context
Searching for the .war file name in the codebase will also reference this class, which makes it easier to find if the file is renamed.
No changing of private final fields for tomcat 8, see here
由于没有一个选项适用于 Tomcat 9.0.19(@Luiz 也提到过),我们使用代码方法并用最少的自定义实现替换了 Tomcat StandardHost 和 HostConfig:
中的 deployApps 函数>HostConfig 必须被重写才能对所有内容进行排序(包括 /webapps 文件夹中的 WAR 文件以及 configbase 文件夹中的描述符 XML 文件(例如 conf/Catalina/localhost)):
然后,我们将新类放入 Tomcat /lib 目录中的新 jar 文件中,并修改 conf/server.xml 文件以用我们自己的实现替换主机类:
在启动期间,Tomcat 按所需顺序加载所有组件。
Since none of the options worked for Tomcat 9.0.19 (the one mentioned by @Luiz also) we used the code approach and replaced the Tomcat StandardHost and HostConfig with minimal custom implementations:
The deployApps function in HostConfig had to be overriden for sorting to work for everything (incl. WAR files in /webapps folder and also for descriptor XML files in configbase folder (e.g. conf/Catalina/localhost)):
Then we placed the new classes in a new jar file in Tomcat /lib directory and modified conf/server.xml file to replace the host class with our own implementation:
During start Tomcat loaded all components in the required order.
理论上,您可以通过
contextInitialized()
中的ExecutorService
生成一个Runnable
,后者会按时间间隔检查其他 Web 应用程序的可用性(可能通过触发 HTTPHEAD
请求?)。一旦其他 Web 应用程序可用,则在 servlet 上下文中设置一些属性来指示这一点。添加一个Filter
来检查该属性是否存在并相应地阻止/继续请求。In theory you could spawn a
Runnable
byExecutorService
incontextInitialized()
which in turn checks the availability of the other webapp at timed intervals (perhaps by firing a HTTPHEAD
request?). Once the other webapp is available, then set some attribute in the servlet context which indicates that. Add aFilter
which checks for the presence of that attribute and blocks/continues requests accordingly.我知道这个问题有点老了,但我在尝试做同样的事情时发现了它,并认为我会用更好的解决方案进行更新...
您可以在 server.xml 中定义多个服务,这些服务在不同的端口上运行。服务根据它们在 server.xml 中出现的顺序依次启动。这意味着您可以在第一个服务中运行配置服务,然后在第二个服务中运行依赖于它的应用程序(我对其余服务使用默认的 Catalina...)
您可以查看更多信息这里:
http://wiki.apache.org/tomcat/FAQ/Miscellaneous#Q27
这是我在 Catalina 服务之前包含的服务:
如您所见,我使用 docbase 而不是 appBase,但如果您愿意,您应该能够配置不同的 appBase...
注意更改服务和引擎的名称很重要。
华泰
I know this question is a bit old, but I found it when trying to do the same thing and thought I'd update with a better solution...
You can define mulitple services in your server.xml, which run on different ports. The services are started sequentially according to the order they appear in the server.xml. This means that you can have - for example - a configuration service running in the first service and then the apps that depend on it in the second (I use the default Catalina one for the rest of them...)
You can see more info here:
http://wiki.apache.org/tomcat/FAQ/Miscellaneous#Q27
And this is the service that I include before the Catalina Service:
As you can see, I use docbase rather than appBase, but you should be able t configure a different appBase if you prefer...
NB it's important to change the name of both the service and the engine.
HTH
这是我用来创建 2 个级别的 Web 应用程序加载的好技巧。不保证每个级别的顺序。这依赖于这样一个事实:tomcat 将首先从 tomcat/conf/[Engine Name]/[Host Name] 加载上下文描述符,然后才从 server.xml 中 Host 元素的 appBase 属性加载上下文,
只需在以下位置添加以下代码:您想要在第二级(即稍后)加载的网络应用程序
Here is a nice trick i use to create 2 levels of webapp loading. in each level the order is not guaranteed. This relies on the fact that tomcat will load first context descriptors from tomcat/conf/[Engine Name]/[Host Name] and only then contexts from the appBase attribute of the Host element in server.xml
Just add the following code somewhere in the webapp you would like to load in the 2nd level ( i.e. later )