我已经在 Jersey tomcat 下为 REST API 部署了一个使用 neo4j java 嵌入式版本的应用程序。通过使用 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;
}
}