java - spring 初始化后预热 Neo4j 数据库

标签 java spring neo4j

我使用具有近 50 万个节点的 Neo4J 数据库。当我启动我的 Spring 应用程序并执行第一个查询时,大约需要 4-5 秒。这只发生在第一个查询中,所以我想我可以在 spring 初始化后进行预热,以使所有后续查询更快。

这是我的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>

我看到等待 Spring bean 初始化的一种方法是实现 ApplicationListener,而使用 Neo 预热数据库的常规方法是调用 apoc.runtime.warmup( ) 函数,所以我做了如下操作:

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.");
    }
}

这个没有用,一切都被正确记录,但第一个 neo4j 查询仍然很慢。

由于这种方法不起作用,我编辑了 executeTestSelect 方法来运行一个真正的查询并像这样处理结果:

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.");
}

这次启动需要 4-5 秒来执行查询,但随后会打印

Neo4j cache done. Processed 0 nodes.

这很奇怪,因为在应用程序完全初始化时运行的完全相同的查询返回 450k 个节点。

我错过了什么?是否有可能在到达 onApplicationEvent 时 Neo4j DB 尚未初始化并且无法执行查询?

如何在完成 spring 应用程序初始化后立即正确预热 neo4j 数据库?

最佳答案

好吧,我发现这个纯粹是运气。

我删除了 ApplicationListener 并在执行预热的方法上创建了一个带有 @Autowired 注释的 @Service 类,它似乎正在工作。

我通过删除一个类字段而没有看到留在此处的 @Autowired 注释发现了这一点,并且它起作用了。我试了几次,热身现在开始起作用了。我不知道它是否记录在 Spring 文档的某处。

这是我的最后一个类:

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.");
    }
}

关于java - spring 初始化后预热 Neo4j 数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44347483/

相关文章:

java - Spring 数据neo4j : count relation By EndNode ID

java - 如何在 Jruby-rack 中配置自定义 servlet?

java - 不同浏览器中的 session 管理

java - 使用javamail获取附件内容

java - Spring 批处理 3,IBM JVM (BackToBackPatternClassifier) 上的配置加载时出错

neo4j - 从Neo4j图删除属性

java - 为什么在某些事件中调用 getLayoutParams() 会抛出异常?例如,onSaveInstanceState

spring - 配置为监听端口 8080 的 Tomcat 连接器失败

javascript - AngularJS 身份验证与 Spring Security CORS 问题

neo4j - Neo4j:它是内存中的图形数据库吗?