2

REST API用のJersey tomcatの下に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;
      }
}
4

3 に答える 3

3

Java は、メモリが GC で使用可能になるとすぐに再利用するとは限りません。ヒープ制限に近づくまで、重要な GC アクションが見られないことに気付くかもしれません。そのため、ヒープ制限を 10 GB に設定しても、メモリが再び急増することがあります。それは必ずしも問題ではありません。

ただし、N x Memory を使用して neo の問題を解決するには、すべてのエンドポイント間で埋め込みインスタンスを共有することを検討する必要があります。おそらくそれをサービスクラスに移動し、エンドポイント間で共有インスタンスを持つことによって. Spring を Jersey で使用している場合は、Spring で接続できるため、簡単に実行できます。

于 2012-08-12T09:18:11.040 に答える
2

すべてのリクエストに対して Neo4j インスタンスを作成する必要はありません。一度だけ作成してから、静的フィールドでハックするか(リクエストごとにリソースインスタンスが再作成されるため)、または@Context.

メモリ使用量について。Neo4j は、使用状況に応じて内部キャッシュを構築し、次回同じクエリをより高速に処理します。そのため、使用済みメモリの一部に相当する可能性があります。

ところで。あなたのグラフはどのくらいの大きさで、あなたが行う典型的な操作は何ですか?

于 2012-08-13T11:58:48.220 に答える
1

Spring または Guice を使用していない場合は、neo4J オブジェクトの静的メンバーと静的初期化を使用することで、これを回避できます。その static を持つことが取引のブレーカーである場合、別のオプションは、静的ファクトリを使用してその neo4J オブジェクトのシングルトンインスタンスを取得することです...

于 2012-08-12T23:05:15.993 に答える