Servlet 多次初始化
Servlet initialized multiple times
我们正在部署一个 IIS 站点,包括几个文件夹、几个虚拟目录和一个 Tomcat 主机。
当运行 Tomcat 8 (8.0.46) on Java 8时,一切正常。
升级到 JDK 9 (OpenJDK 64-Bit Server VM (build 9.0.4+11, mixed mode)) 后,我们注意到每个 servlet 都被初始化了几次(即方法 init(ServletConfig ) 执行了多次),第一次在主机上下文中执行(正如预期的那样),并为站点中的每个文件夹更改一次。
不良副作用是 servlet 创建的临时 files/logs 在站点的每个文件夹中重复。
Tomcat server.xml 包含主机定义:
<Host name="localhost" appBase="C:/Program Files (x86)/b4/Controller/bin/webserver/ebsc_web"
unpackWARs="true" autoDeploy="true">
<Context path="/servlets" docBase="C:/Program Files (x86)/b4/Controller/bin/webserver\ebsc_web\" xmlValidation="false" xmlNamespaceAware="false">
<WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
同样的位置(C:\Program Files (x86)\b4\Controller\bin\webserver\ebsc_web)是网站的物理路径,包括子文件夹,例如:小程序、图片等。启动时Tomcat 日志创建在默认位置 (ebsc_web) 并在每个子文件夹中复制。
我们注意到,当在正确的 servlet 上下文中初始化 servlet 时,堆栈为:
Daemon Thread [localhost-startStop-1] (Suspended (breakpoint at line 49 in UpdateSchedulerLoader))
owns: StandardWrapper (id=63)
owns: StandardContext (id=64)
UpdateSchedulerLoader.init(ServletConfig) line: 49
StandardWrapper.initServlet(Servlet) line: 1227
StandardWrapper.loadServlet() line: 1140
StandardWrapper.load() line: 1027
StandardContext.loadOnStartup(Container[]) line: 5038
StandardContext.startInternal() line: 5348
StandardContext(LifecycleBase).start() line: 145
ContainerBase$StartChild.call() line: 1408
ContainerBase$StartChild.call() line: 1398
FutureTask<V>.run() line: 264
ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1167
ThreadPoolExecutor$Worker.run() line: 641
Thread.run() line: 844
但是在使用指向子文件夹的 servlet 上下文初始化它的任何后续时间,堆栈是:
Daemon Thread [localhost-startStop-1] (Suspended (breakpoint at line 42 in UpdateSchedulerLoader))
owns: StandardWrapper (id=154)
owns: StandardContext (id=144)
UpdateSchedulerLoader.init(ServletConfig) line: 42
StandardWrapper.initServlet(Servlet) line: 1227
StandardWrapper.loadServlet() line: 1140
StandardWrapper.load() line: 1027
StandardContext.loadOnStartup(Container[]) line: 5038
StandardContext.startInternal() line: 5348
StandardContext(LifecycleBase).start() line: 145
StandardHost(ContainerBase).addChildInternal(Container) line: 753
StandardHost(ContainerBase).addChild(Container) line: 729
StandardHost.addChild(Container) line: 717
HostConfig.deployDirectory(ContextName, File) line: 1129
HostConfig$DeployDirectory.run() line: 1871
Executors$RunnableAdapter<T>.call() line: 514
FutureTask<V>.run() line: 264
ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1167
ThreadPoolExecutor$Worker.run() line: 641
Thread.run() line: 844
所以 servlet 第一次由 ContainerBase$StartChild.call()
初始化,后来由 HostConfig.deployDirectory(ContextName, File)
...
你能explain/fix这种行为吗?
根据@PiotrP.Karwasz 的指示,通过在 server.xml.
的主机配置中同时设置 autoDeploy="false" deployOnStartup="false"
,问题已解决
我们正在部署一个 IIS 站点,包括几个文件夹、几个虚拟目录和一个 Tomcat 主机。
当运行 Tomcat 8 (8.0.46) on Java 8时,一切正常。
升级到 JDK 9 (OpenJDK 64-Bit Server VM (build 9.0.4+11, mixed mode)) 后,我们注意到每个 servlet 都被初始化了几次(即方法 init(ServletConfig ) 执行了多次),第一次在主机上下文中执行(正如预期的那样),并为站点中的每个文件夹更改一次。
不良副作用是 servlet 创建的临时 files/logs 在站点的每个文件夹中重复。
Tomcat server.xml 包含主机定义:
<Host name="localhost" appBase="C:/Program Files (x86)/b4/Controller/bin/webserver/ebsc_web"
unpackWARs="true" autoDeploy="true">
<Context path="/servlets" docBase="C:/Program Files (x86)/b4/Controller/bin/webserver\ebsc_web\" xmlValidation="false" xmlNamespaceAware="false">
<WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
同样的位置(C:\Program Files (x86)\b4\Controller\bin\webserver\ebsc_web)是网站的物理路径,包括子文件夹,例如:小程序、图片等。启动时Tomcat 日志创建在默认位置 (ebsc_web) 并在每个子文件夹中复制。
我们注意到,当在正确的 servlet 上下文中初始化 servlet 时,堆栈为:
Daemon Thread [localhost-startStop-1] (Suspended (breakpoint at line 49 in UpdateSchedulerLoader))
owns: StandardWrapper (id=63)
owns: StandardContext (id=64)
UpdateSchedulerLoader.init(ServletConfig) line: 49
StandardWrapper.initServlet(Servlet) line: 1227
StandardWrapper.loadServlet() line: 1140
StandardWrapper.load() line: 1027
StandardContext.loadOnStartup(Container[]) line: 5038
StandardContext.startInternal() line: 5348
StandardContext(LifecycleBase).start() line: 145
ContainerBase$StartChild.call() line: 1408
ContainerBase$StartChild.call() line: 1398
FutureTask<V>.run() line: 264
ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1167
ThreadPoolExecutor$Worker.run() line: 641
Thread.run() line: 844
但是在使用指向子文件夹的 servlet 上下文初始化它的任何后续时间,堆栈是:
Daemon Thread [localhost-startStop-1] (Suspended (breakpoint at line 42 in UpdateSchedulerLoader))
owns: StandardWrapper (id=154)
owns: StandardContext (id=144)
UpdateSchedulerLoader.init(ServletConfig) line: 42
StandardWrapper.initServlet(Servlet) line: 1227
StandardWrapper.loadServlet() line: 1140
StandardWrapper.load() line: 1027
StandardContext.loadOnStartup(Container[]) line: 5038
StandardContext.startInternal() line: 5348
StandardContext(LifecycleBase).start() line: 145
StandardHost(ContainerBase).addChildInternal(Container) line: 753
StandardHost(ContainerBase).addChild(Container) line: 729
StandardHost.addChild(Container) line: 717
HostConfig.deployDirectory(ContextName, File) line: 1129
HostConfig$DeployDirectory.run() line: 1871
Executors$RunnableAdapter<T>.call() line: 514
FutureTask<V>.run() line: 264
ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1167
ThreadPoolExecutor$Worker.run() line: 641
Thread.run() line: 844
所以 servlet 第一次由 ContainerBase$StartChild.call()
初始化,后来由 HostConfig.deployDirectory(ContextName, File)
...
你能explain/fix这种行为吗?
根据@PiotrP.Karwasz 的指示,通过在 server.xml.
的主机配置中同时设置autoDeploy="false" deployOnStartup="false"
,问题已解决