Warmup Neo4j database after spring initialization

I am using a Neo4J database with nearly 500k nodes. When I launch the Spring application and execute the first request, it takes about 4-5 seconds. This only happens for the first request, so I thought I could do a warm-up after initializing Spring to make all subsequent requests faster.

This is my applicationContext.xml :

 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <!-- neo4j database --> <util:map id="config"> <entry key="enable_remote_shell" value="false" /> </util:map> <bean id="graphDbFactory" class="org.neo4j.graphdb.factory.GraphDatabaseFactory" /> <bean id="graphDbBuilder" factory-bean="graphDbFactory" factory-method="newEmbeddedDatabaseBuilder"> <constructor-arg value="/path/to/db" /> </bean> <bean id="graphDbBuilderFinal" factory-bean="graphDbBuilder" factory-method="setConfig"> <constructor-arg ref="config" /> </bean> <bean id="graphDatabaseService" factory-bean="graphDbBuilderFinal" factory-method="newGraphDatabase" destroy-method="shutdown" class="org.neo4j.graphdb.GraphDatabaseService"/> <context:component-scan base-package="com.app.components" /> </beans> 

I saw that one of the ways to wait for Spring beans to initialize was to implement ApplicationListener , and the regular way to defrost a database using Neo was to call apoc.runtime.warmup() , so I did the following

 package com.app.components; @Component public class StartupTasks implements ApplicationListener<ContextRefreshedEvent> { private static final Logger LOG = LogManager.getLogger(StartupTasks.class); @Autowired GraphDatabaseService db; @Override public void onApplicationEvent(ContextRefreshedEvent event) { executeTestSelect(); } private void executeTestSelect() { LOG.info("Warming up Neo4j..."); Transaction tx = db.beginTx(); db.execute("CALL apoc.warmup.run()"); tx.close(); LOG.info("Warmup complete."); } } 

This does not work, everything is logged correctly, but the first neo4j request is still slow.

Since this approach did not work, I edited the executeTestSelect to run the real query and process the results as follows:

 private void executeTestSelect() { String textToSearch = "a"; // returns almost all nodes, should make neo4j cache them all Transaction tx = db.beginTx(); Map<String, Object> params = new HashMap<String, Object>(); params.put("textToSearch", textToSearch ); Result resultSet = db.execute("MATCH (n:PROD) WHERE n.description CONTAINS {textToSearch} RETURN n", params); Iterator<Node> results = resultSet.columnAs("n"); int count = 0; while (results.hasNext()) { results.next(); count++: } tx.close(); LOG.info("Neo4j cache done. Processed " + count + " nodes."); } 

This time, the launch takes 4-5 seconds to complete the request, but then it prints

Completed Neo4j cache. Processed 0 nodes.

This is strange, because the same request is launched when the application is fully initialized, it returns 450 thousand nodes.

What am I missing? Is it possible that upon reaching onApplicationEvent , the Neo4j database is not yet initialized and cannot complete queries?

How to warm up the neo4j database right after the Spring application is fully initialized?

+5
source share
1 answer

Well, I discovered this by pure chance.

I removed ApplicationListener and created the @Service class with the @Service annotation in a method that does the warm-up seems to work.

I found this by deleting the class field without seeing the @Autowired annotation @Autowired , and it worked. I tried this several times, now the workout is working. I don't know if this is documented anywhere in the Spring documentation.

This is my last class:

 package com.app.components; @Component public class Neo4jWarmup { private static final Logger LOG = LogManager.getLogger(StartupTasks.class); @Autowired GraphDatabaseService db; /* * this did the trick - the method gets called * after Spring initialization and the DB works as expected */ @Autowired public void neo4jWarmup() { executeTestSelect(); } private void executeTestSelect() { LOG.info("Warming up Neo4j..."); Transaction tx = db.beginTx(); db.execute("CALL apoc.warmup.run()"); tx.close(); LOG.info("Warmup complete."); } } 
+1
source

Source: https://habr.com/ru/post/1268512/


All Articles