无法在 Tomcat webapp 中关闭 Neo4j Jetty 服务器 [英] Unable to shut down Neo4j Jetty server within Tomcat webapp
问题描述
目前我正在开发一个使用 Neo4j 的网络应用程序.我们的应用需要部署在Tomcat环境中(客户要求).我们决定嵌入 Neo4j,因为这样我们可以使用 Neo4j 提供的 Java API,它更容易部署并且我们获得了改进的性能.但是,我们还需要访问 REST API,因为我们有一个用 Angular 编写的单页 web 应用程序,它目前正在使用这个接口.然而,嵌入式 Neo4j 数据库不公开 REST api.Neo4j-server 工件包含可以使用嵌入式图形数据库引导码头服务器的代码.所以我们的 Tomcat webapp 正在启动一个 Jetty 服务器.我们可以通过一个端口(8080)上部署在Tomcat中的webapp和另一个端口(7474)上的Neo4j REST接口和Neo4j浏览器访问graphDb.尽管这有点奇怪,但它工作正常,除非我们尝试停止我们的 web 应用程序(例如重新部署).关闭我们的 web 应用程序时,我们从 tomcat 收到以下错误:
Currently I am working on an webapp that utilizes Neo4j. Our app needs to be deployed in a Tomcat environment (customer requirement). We decided to embed Neo4j, because that way we can use the Neo4j provided Java API, it's easier to deploy and we get improved performance. However, we also need access to the REST API, because we have a single page webapp written in Angular that is currently making use this interface. The embedded Neo4j database however does not expose the REST api. The Neo4j-server artifact contains code that can bootstrap a jetty server with an embedded graph database. So our Tomcat webapp is starting a Jetty server. We can access the graphDb via the webapp deployed in Tomcat on one port (8080) and the Neo4j REST interface and Neo4j browser on another port (7474). Though this is a bit odd it works fine, except for when we try to stop our webapp (for redeployment for example). When shutting down our webapp we receive these errors from tomcat:
SEVERE: The web application [/chainmonitor] appears to have started a thread named [GC-Monitor] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [RRD4J Sync Pool [Thread-1]] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [Statistics Gatherer[primitives]] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [pool-1-thread-1] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [pool-1-thread-2] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [DateCache] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [qtp835579386-31-selector-3] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [qtp835579386-32-selector-0] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [qtp835579386-33-selector-1] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [qtp835579386-34-selector-2] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [qtp835579386-35-selector-4] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [qtp835579386-36-selector-5] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [qtp835579386-37-acceptor-0-ServerConnector@1425c689{HTTP/1.1}{localhost:7474}] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [qtp835579386-38-acceptor-1-ServerConnector@1425c689{HTTP/1.1}{localhost:7474}] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [HashSessionScavenger-0] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/chainmonitor] appears to have started a thread named [qtp835579386-54] but has failed to stop it. This is very likely to create a memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [org.eclipse.jetty.http.HttpFields$1] (value [org.eclipse.jetty.http.HttpFields$1@4a3d3a5e]) and a value of type [org.eclipse.jetty.http.HttpFields.DateGenerator] (value [org.eclipse.jetty.http.HttpFields$DateGenerator@24f0137b]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:17 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/chainmonitor] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@281a099d]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
jun 10, 2014 6:43:27 PM org.apache.catalina.startup.HostConfig undeploy
INFO: Undeploying context [/chainmonitor]
jun 10, 2014 6:43:27 PM org.apache.catalina.startup.ExpandWar deleteDir
SEVERE: [C:devapache-tomcat-7.0.54webappschainmonitorWEB-INFlib] could not be completely deleted. The presence of the remaining files may cause problems
jun 10, 2014 6:43:27 PM org.apache.catalina.startup.ExpandWar deleteDir
SEVERE: [C:devapache-tomcat-7.0.54webappschainmonitorWEB-INF] could not be completely deleted. The presence of the remaining files may cause problems
jun 10, 2014 6:43:27 PM org.apache.catalina.startup.ExpandWar deleteDir
SEVERE: [C:devapache-tomcat-7.0.54webappschainmonitor] could not be completely deleted. The presence of the remaining files may cause problems
jun 10, 2014 6:43:27 PM org.apache.catalina.startup.ExpandWar delete
SEVERE: [C:devapache-tomcat-7.0.54webappschainmonitor] could not be completely deleted. The presence of the remaining files may cause problems
我们的 pom.xml 看起来像这样:
Our pom.xml looks like this:
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>2.0.3</version>
</dependency>
<dependency>
<groupId>org.neo4j.app</groupId>
<artifactId>neo4j-server</artifactId>
<version>2.0.3</version>
</dependency>
这是我们如何启动嵌入式数据库并启动jetty服务器:
This is how we start the embedded database and start the jetty server:
graphDb = (EmbeddedGraphDatabase) new GraphDatabaseFactory().
newEmbeddedDatabaseBuilder(dataDir).loadPropertiesFromURL(Neo4jPropertiesUrl).newGraphDatabase();
bootstrapper = new WrappingNeoServerBootstrapper(graphDb);
目前neo4j-server.properties 是空的.我没有尝试过很多不同的配置,但这样做似乎没有问题.
Currently neo4j-server.properties is empty. I've not tried many different configurations, but doing so doesn't seem to be a problem.
这是我们如何停止嵌入式数据库和码头服务器:
This is how we stop the embedded database and jetty server:
@Override
public void contextDestroyed(ServletContextEvent event) {
graphDb.shutdown();
bootstrapper.stop();
}
这显然是由Tomcat的内存泄漏保护引起的(http://wiki.apache.org/tomcat/内存泄漏保护).
This is apparently caused by Tomcat's memory leak protection (http://wiki.apache.org/tomcat/MemoryLeakProtection).
结果是我们的webapp只能通过彻底kill掉Tomcat进程(kill -9)才能重新部署,这是非常不可取的.
The result is that our webapp can only be redeployed by completely killing the Tomcat process (kill -9), which is very undesirable.
我们尝试了很多方法:
- 不关闭嵌入式 grapbDb.没有效果.
- 没有明确关闭引导程序.没有效果.(引导程序有自己的关闭钩子)
- 先关闭引导程序,然后关闭嵌入式数据库.
- 线程自焚者:https://github.com/Neo4j/Neo4j/issues/1070一>.该代码运行并牺牲了 59 个线程局部值,但没有明显效果.有趣的是,当我在关闭期间循环运行它一分钟时,它一直说它牺牲了 6 个值.对我来说,这表明这个过程根本不起作用,因为 Neo4j 在关闭时需要一些时间.
- 在关闭后延迟.我们尝试这样做的原因是因为在 tomcat 收到关闭信号后,我们需要等待几秒钟才能真正终止进程,否则我们在下次启动时会收到错误消息,表明我们的图形数据已损坏(带有未已正确关闭).延迟 5 秒以上似乎也有影响,因为之后我们只得到 6 个严重错误而不是 16 个.这也是我认为自焚过程根本不起作用的原因.
- 我们尝试将我们的嵌入式 Neo4j 添加到集群中作为替代方案,从而能够同时使用 REST api 和嵌入式 Neo4j.然而,经过大约四个小时的尝试,我们放弃了.在嵌入式 Neo4j 数据库启动期间,我们的 web 应用程序就停止了.经过一些调试后,它看起来很像 Neo4j 代码中的一个死锁.我们尝试将所有 HA 超时配置设置为一些较小的值,但没有任何效果.
- not shutting down the embedded grapbDb. No effect.
- not explicitly shutting down the bootstrapper. No effect. (the bootstrapper has its own shutdown hook)
- shutting down the bootstrapper first and then the embedded database.
- thread immolator: https://github.com/Neo4j/Neo4j/issues/1070 . The code runs and immolates 59 thread local values, but with no apparent effect. Interestingly when I run this in a loop for a minute during the shutdown it keeps saying it immolated 6 values. To me this is an indication that this process does not work at all, because Neo4j takes some time while shutting down.
- putting in a delay after the shutting down. The reason we tried this is because after tomcat has received a shutdown signal we need to wait a few seconds before actually killing the process otherwise we get an error on our next start that our graph data has been corrupted (with a message that is has not been properly shut down). Delaying by 5+ seconds seems to have an effect too, because afterwards we get only 6 severe errors instead of 16. This is also the reason why I think the immolation process is not working at all.
- We tried as an alternative to add our embedded Neo4j to a cluster, thus being able to use both the REST api as wel as the embedded Neo4j. However after about four hours trying to get this to work we gave up. During the startup of the embedded Neo4j database our webapplication just froze. After some debugging it very much seemed like a deadlock within Neo4j's code. We tried to set all HA timeout configurations to some smaller values, but with no effect.
问题是由 Neo4j 码头服务器引起的.没有它就不会出现这个问题.不过,我们需要 REST API.你知道我们如何解决这个问题吗?或者您是否有在 Tomcat 环境中使用嵌入式数据库和 REST API 的替代方法?
The problem is caused by the Neo4j jetty server. Without it this problem does not arise. We need the REST API though. Do you know how we can fix this? Or have you got an alternative way to use the embedded database and the REST API within a Tomcat environment?
我们正在使用:
- Java:1.7.0_60
- Tomcat 7.0.54
- Neo4j:2.0.3(我们尝试过 2.1.1,但得到了完全相同的结果)
- 在 Windows 7 和 Linux Redhat 上观察到相同的行为
推荐答案
我们有一个非常相似的设置和需求.这是我们针对此问题的解决方案.JVM 运行时shutdownHook 在Tomcat 中不起作用,因此我们持有对包含GraphDatabaseService 的包装器对象的引用,并将该包装器放置在存储库管理器对象中.在存储库管理器对象中的方法上使用 @PreDestroy 注释,这将在存储库管理器类被销毁之前关闭存储库.
We have a very similar setup and need. Here is the solution we have for this issue. The JVM Runtime shutdownHook does not work in Tomcat, so we hold a reference to a wrapper object holding our GraphDatabaseService and place that wrapper in a repository manager object. Use the @PreDestroy annotation on a method in the repository manager object which will shutdown the repositories before the repository manager class is destroyed.
import javax.annotation.PreDestroy;
...
@PreDestroy
public void destroy() {
log.info("Destroying Neo4jRepositoryManager...");
shutdown(Neo4jPropertyKeys.SANDBOX_DATABASE.getUrlKey());
shutdown(Neo4jPropertyKeys.PRODUCTION_DATABASE.getUrlKey());
shutdown(Neo4jPropertyKeys.TEST_DATABASE.getUrlKey());
}
private void shutdown(String urlKey) {
if(repositories.containsKey(urlKey)) {
LabeledNodeGraphRepository graphdb = repositories.get(urlKey);
graphdb.getGraphDatabaseService().shutdown();
log.info(urlKey + " shutdown...");
}
}
<bean id="repositoryManager" class="mypath.neo4j.repository.Neo4jRepositoryManager"/>
我们的环境是:
- Java 1.7.0_72
- Tomcat 7.0.56
- Neo4j 2.1.6
- Spring 4.0.5
- 球衣 2.1.4
这篇关于无法在 Tomcat webapp 中关闭 Neo4j Jetty 服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!