我已经在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
用辛格尔顿更新
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服务器中使用带有@Context注入的Provider.
关于内存使用情况. Neo4j根据您的使用情况建立内部缓存,以在下一次更快地处理相同的查询.因此,这可能相当于一些已用的内存.
顺便说一句.您的图形有多大?您执行的典型操作是什么?