2014-06-12 61 views
1

目前我正在開發一個使用Neo4j的web應用程序。我們的應用程序需要部署在Tomcat環境中(客戶需求)。我們決定嵌入Neo4j,因爲這樣我們可以使用Neo4j提供的Java API,它更易於部署,並且性能得到改善。但是,我們還需要訪問REST API,因爲我們有一個使用Angular編寫的單頁web應用程序,目前正在使用此接口。但是,嵌入式Neo4j數據庫不公開REST API。 Neo4j服務器工件包含可以使用嵌入式圖形數據庫引導碼頭服務器的代碼。所以我們的Tomcat webapp啓動了一個Jetty服務器。我們可以通過在一個端口(8080)上部署Tomcat的webapp以及在另一個端口(7474)上的Neo4j REST接口和Neo4j瀏覽器來訪問graphDb。雖然這有點奇怪,但它工作正常,除了當我們試圖阻止我們的Web應用程序(例如重新部署)。當關閉我們的web應用程序,我們收到這些錯誤從Tomcat:無法關閉Tomcat內的Neo4j Jetty服務器webapp

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 [[email protected]{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 [[email protected]{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 [[email protected]]) and a value of type [org.eclipse.jetty.http.HttpFields.DateGenerator] (value [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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 [[email protected]]) 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:\dev\apache-tomcat-7.0.54\webapps\chainmonitor\WEB-INF\lib] 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:\dev\apache-tomcat-7.0.54\webapps\chainmonitor\WEB-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:\dev\apache-tomcat-7.0.54\webapps\chainmonitor] 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:\dev\apache-tomcat-7.0.54\webapps\chainmonitor] could not be completely deleted. The presence of the remaining files may cause problems 

我們的pom.xml如下:

<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> 

這是我們如何啓動嵌入式數據庫並啓動碼頭服務器:

graphDb = (EmbeddedGraphDatabase) new GraphDatabaseFactory(). 
     newEmbeddedDatabaseBuilder(dataDir).loadPropertiesFromURL(Neo4jPropertiesUrl).newGraphDatabase(); 
bootstrapper = new WrappingNeoServerBootstrapper(graphDb); 

當前neo4j-server.properties爲空。我沒有嘗試過很多不同的配置,但是這樣做似乎不成問題。

這是我們如何停止嵌入式數據庫和碼頭服務器:

@Override 
    public void contextDestroyed(ServletContextEvent event) { 
​   graphDb.shutdown(); 
      bootstrapper.stop(); 
    } 

這顯然是Tomcat的內存泄漏防護(http://wiki.apache.org/tomcat/MemoryLeakProtection)引起的。

結果是我們的webapp只能通過完全殺死Tomcat進程(kill -9)來重新部署,這是非常不可取的。

我們已經嘗試了一堆東西:

  • 沒有關閉嵌入式grapbDb。沒有效果。
  • 未明確關閉引導程序。沒有效果。 (引導程序有自己的關閉鉤子)
  • 先關閉引導程序,然後關閉嵌入式數據庫。
  • 線程免責:https://github.com/Neo4j/Neo4j/issues/1070。代碼運行並移除了59個線程本地值,但沒有明顯效果。有趣的是,當我在停機期間循環運行一分鐘時,它一直說它將6個值固定。對我來說,這表明這個過程根本不起作用,因爲Neo4j在關機時需要一些時間。
  • 關機後延遲。我們嘗試這樣做的原因是因爲在tomcat收到關閉信號後,我們需要等待幾秒鐘才能真正殺死進程,否則我們在下一次啓動時出現錯誤,表明我們的圖形數據已損壞(消息沒有被正確關閉)。延遲5秒以上似乎也有影響,因爲之後我們只得到6次嚴重錯誤而不是16次。這也是爲什麼我認爲焚燒過程根本不起作用的原因。
  • 我們嘗試將我們的嵌入式Neo4j添加到集羣,因此可以同時使用REST API和嵌入式Neo4j。然而,經過大約四個小時試圖讓這個工作,我們放棄了。在嵌入式Neo4j數據庫的啓動過程中,我們的web應用程序剛剛凍結。經過一些調試後,它非常像Neo4j代碼中的死鎖。我們嘗試將所有HA超時配置設置爲一些較小的值,但不起作用。

該問題是由Neo4j碼頭服務器引起的。沒有它,這個問題不會出現。儘管我們需要REST API。你知道我們如何解決這個問題嗎?或者您有沒有其他方法可以在Tomcat環境中使用嵌入式數據庫和REST API?

我們使用:

  • 的Java:1.7.0_60
  • 的Tomcat 7.0.54
  • 的Neo4j:2.0.3(我們已經嘗試2.1.1,但得到完全相同的結果)
  • 在Windows 7和Linux上觀察到相同的問題Redhat
+0

如果您「需要」Neo4j REST API,那麼您應該運行Neo4j服務器。請注意,Neo4j服務器支持非託管擴展,它們是Java代碼並且可以完全訪問Java API。 Neo4j服務器負責通過與REST API使用的相同的HTTP服務器提供對這些API的訪問。 –

回答

0

您可能泄漏的交易尚未關閉,那麼Neo4j會等待20秒關閉關閉這些交易。

如果您等待5秒以上,那些報告的問題仍然存在?

+0

即使我剛啓動Neo4j並關閉它,我也會遇到這個問題。我也等了120秒,沒有明顯的效果。 –

0

我們有一個非常類似的設置和需要。這是我們解決這個問題的解決方案。 JVM Runtime shutdownHook在Tomcat中不起作用,因此我們持有對包含GraphDatabaseService的包裝器對象的引用,並將該包裝器放入存儲器管理器對象中。對資源庫管理器對象中的方法使用@PreDestroy批註,這會在資源庫管理器類被銷燬之前關閉資源庫。

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
  • 春4.0 .5
  • Jersey 2.1.4