Java neo4j, REST и память
Я развернул приложение с использованием встроенной Java-версии neo4j под Jersey Tomcat для REST API. Измеряя использование памяти с помощью jconsole, я заметил, что каждый вызов REST добавляет 200 МБ памяти (что, я думаю, связано с тем, что весь график загружается в память). Поэтому всего за 5 вызовов сервер выделяет 1 ГБ памяти, что очень много! Чтобы очистить память, мне нужно дождаться сборщика мусора (пороговое значение установлено на 1 Гб).
Это нормальное поведение, потому что я использую Java-версию neo4j или я делаю что-то ужасно неправильное? Что я должен сделать, чтобы освободить память после завершения вызова 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();
}
Спасибо, Daniele
-------- ПОЛНЫЙ КОД КЛАССА ----------
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;
}
}