我已经在Jersey tomcat下使用Neo4j Java嵌入式版本针对REST API部署了一个应用程序。通过使用jconsole测量内存使用情况,我注意到每个REST调用都会增加200Mb的内存(我认为这是因为整个图形都已加载到内存中)。因此,仅用5个调用,服务器便分配了1Gb的内存!要清理内存,我必须等待垃圾收集器(阈值设置为1Gb)。
这是因为我使用的是neo4j java嵌入式版本,还是正常的行为?当API调用结束时,我应该怎么做以释放内存?
下面是示例代码:
@GET @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8") public Response getApi( @QueryParam("q") String query){ try{ // new neo instance here with EmbeddedGraphDatabase ... some code // stop neo }catch(Exception ex){ // stop neo } return response.ok("json data here").build(); }
谢谢,丹妮尔
--------完整的分类代码----------
import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.kernel.EmbeddedGraphDatabase; @Path("/API") public class API { @GET @Produces(MediaType.APPLICATION_JSON) public Response apiCall(@QueryParam("q") String query){ GraphDatabaseService graphDb; try{ // start neo graphDb = new EmbeddedGraphDatabase( "/var/neo4jdb/" ); this.registerShutdownHook( graphDb ); // API + NEO code here.. // stop neo graphDb.shutdown(); }catch(Exception ex){ // stop neo graphDb.shutdown(); } Response response = null; return response.ok("This is your query: "+query).build(); } /** * Server shutdown */ public void registerShutdownHook( final GraphDatabaseService graphDb ){ // Registers a shutdown hook for the Neo4j instance so that it // shuts down nicely when the VM exits (even if you "Ctrl-C" the // running example before it's completed) Runtime.getRuntime() .addShutdownHook( new Thread() { @Override public void run() { graphDb.shutdown(); } } ); } }
然后我像这样通过浏览器调用REST服务 http://localhost:8080/API?q=test
http://localhost:8080/API?q=test
import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.kernel.EmbeddedGraphDatabase; @Path("/API") public class API { @GET @Produces(MediaType.APPLICATION_JSON) public Response apiCall(@QueryParam("q") String query){ GraphDatabaseService graphDb; try{ // start neo Neo4jSingleton neo4jInstance = new Neo4jSingleton(); GraphDatabaseService graphDb = null; graphDb = neo4jInstance.getInstance(DB_PATH); this.registerShutdownHook( graphDb ); // API + NEO code here.. // cypher query ExecutionEngine engine = new ExecutionEngine(graphDb); String queryString = "Cypher query code"; ExecutionResult result = engine.execute( queryString ); // fetch results here.. // never stop neo now with singleton }catch(Exception ex){ // stop neo graphDb.shutdown(); } Response response = null; return response.ok("This is your query: "+query).build(); } /** * Server shutdown */ public void registerShutdownHook( final GraphDatabaseService graphDb ){ // Registers a shutdown hook for the Neo4j instance so that it // shuts down nicely when the VM exits (even if you "Ctrl-C" the // running example before it's completed) Runtime.getRuntime() .addShutdownHook( new Thread() { @Override public void run() { graphDb.shutdown(); } } ); } } public class Neo4jSingleton { private static GraphDatabaseService db; public Neo4jSingleton() { } /* * il metodo di restituire un'unica istanza * contenente il database neo4j */ public static GraphDatabaseService getInstance(String DB_PATH) { //Boolean isDbChange=verifyDbChange(); if (db == null /*|| isDbChange*/) { db = new EmbeddedGraphDatabase(DB_PATH); } return db; } }
您不能为每个请求都创建Neo4j实例。请只创建一次,然后将其传递给您,要么在静态字段中变乱(因为您是为每个请求重新创建资源实例),要么在Neo4j服务器中注入了Provider @Context。
@Context
关于内存使用情况。Neo4j根据您的使用情况构建内部缓存,以在下一次更快地处理相同的查询。因此,这可能相当于一些已用的内存。
顺便说一句。您的图形有多大?您执行的典型操作是什么?