简体   繁体   English

java中的并发gremlin-server和graph查询

[英]Concurrent gremlin-server and graph queries in java

I'm writing a Java application with TinkerPop3. 我正在用TinkerPop3编写Java应用程序。 It communicates with a Neo4j graph and sends read/write queries through Gremlin using the neo4j-gremlin 3.0.0.M7 libraries. 它与Neo4j图进行通信,并使用neo4j-gremlin 3.0.0.M7库通过Gremlin发送读/写查询。

Concurrently, I would like to make this graph available through HTTP using gremlin-server 3.0.0.M7 . 同时,我想使用gremlin-server 3.0.0.M7通过HTTP提供此图。 Separately, these operations work perfectly fine. 另外,这些操作完全正常。 However, it seems that this is not possible concurrently due to multiple connections not being allowed (ie the GremlinServer object and the Java code both try to obtain the lock on the graph). 但是,由于不允许多个连接(即GremlinServer对象和Java代码都试图获取图上的锁),似乎不可能同时进行此操作。

Of course, a workaround could involve creating a Client from within the Java program and connect it to the server. 当然,解决方法可能涉及从Java程序中创建客户端并将其连接到服务器。 However, I would rather eliminate the communication overhead this introduces. 但是,我宁愿消除这引入的通信开销。

The big question: is this possible? 最大的问题是:这有可能吗?

For completeness, here's my minimal code. 为了完整起见,这是我的最小代码。 Note that my gremlin-server-neo4j.yaml refers to the standardly included neo4j-empty.properties file, containing the same neo4j graph data directory as the Neo4jGraph object in my Java code (ie /tmp/neo4j ). 请注意,我的gremlin-server-neo4j.yaml引用了标准包含的neo4j-empty.properties文件,其中包含与我的Java代码中的Neo4jGraph对象相同的neo4j图形数据目录(即/tmp/neo4j )。

import com.tinkerpop.gremlin.neo4j.structure.Neo4jGraph;
import com.tinkerpop.gremlin.server.GremlinServer;
import com.tinkerpop.gremlin.server.Settings;    

public class Main {

    Neo4jGraph g;
    GremlinServer s;

    public static void main (String[] argv) {
        new Main().start();
    }

    private void start () {

        try {
            Settings settings = Settings.read(getClass().getResourceAsStream("/gremlin-server-neo4j.yaml"));
            s = new GremlinServer(settings);
            s.run();
        } catch (Exception e) {
            e.printStackTrace();
        }

        g = Neo4jGraph.open("/tmp/neo4j");

        // Gremlin code here

        g.close();
        s.stop();
    }
}

And, finally, the exception: 最后,例外:

Exception in thread "main" java.lang.RuntimeException: Error starting org.neo4j.kernel.EmbeddedGraphDatabase, /tmp/neo4j
    at com.tinkerpop.gremlin.neo4j.structure.Neo4jGraph.<init>(Neo4jGraph.java:160)
    at com.tinkerpop.gremlin.neo4j.structure.Neo4jGraph.open(Neo4jGraph.java:175)
    at com.tinkerpop.gremlin.neo4j.structure.Neo4jGraph.open(Neo4jGraph.java:184)
    at org.test.Main.start(Main.java:33)
    at org.test.Main.main(Main.java:15)
Caused by: java.lang.RuntimeException: Error starting org.neo4j.kernel.EmbeddedGraphDatabase, /tmp/neo4j
    at org.neo4j.kernel.InternalAbstractGraphDatabase.run(InternalAbstractGraphDatabase.java:366)
    at org.neo4j.kernel.EmbeddedGraphDatabase.<init>(EmbeddedGraphDatabase.java:59)
    at org.neo4j.graphdb.factory.GraphDatabaseFactory$1.newDatabase(GraphDatabaseFactory.java:91)
    at org.neo4j.graphdb.factory.GraphDatabaseBuilder.newGraphDatabase(GraphDatabaseBuilder.java:181)
    at com.tinkerpop.gremlin.neo4j.structure.Neo4jGraph.<init>(Neo4jGraph.java:133)
    ... 4 more
Caused by: org.neo4j.kernel.lifecycle.LifecycleException: Component 'org.neo4j.kernel.StoreLockerLifecycleAdapter@67ec8477' was successfully initialized, but failed to start. Please see attached cause exception.
    at org.neo4j.kernel.lifecycle.LifeSupport$LifecycleInstance.start(LifeSupport.java:513)
    at org.neo4j.kernel.lifecycle.LifeSupport.start(LifeSupport.java:115)
    at org.neo4j.kernel.InternalAbstractGraphDatabase.run(InternalAbstractGraphDatabase.java:343)
    ... 8 more
Caused by: org.neo4j.kernel.StoreLockException: Unable to obtain lock on store lock file: /tmp/neo4j/store_lock. Please ensure no other process is using this database, and that the directory is writable (required even for read-only access)
    at org.neo4j.kernel.StoreLocker.checkLock(StoreLocker.java:82)
    at org.neo4j.kernel.StoreLockerLifecycleAdapter.start(StoreLockerLifecycleAdapter.java:44)
    at org.neo4j.kernel.lifecycle.LifeSupport$LifecycleInstance.start(LifeSupport.java:507)
    ... 10 more
Caused by: java.io.IOException: Unable to lock org.neo4j.kernel.impl.nioneo.store.StoreFileChannel@baf1bb3
    at org.neo4j.kernel.impl.nioneo.store.FileLock.wrapFileChannelLock(FileLock.java:38)
    at org.neo4j.kernel.impl.nioneo.store.FileLock.getOsSpecificFileLock(FileLock.java:93)
    at org.neo4j.kernel.DefaultFileSystemAbstraction.tryLock(DefaultFileSystemAbstraction.java:93)
    at org.neo4j.kernel.StoreLocker.checkLock(StoreLocker.java:74)
    ... 12 more

As you've found, what you are trying to do won't work because two separate processes cannot work on the embedded Neo4jGraph . 正如您所发现的那样,您尝试做的事情将无法工作,因为两个独立的进程无法在嵌入式Neo4jGraph As it stands you can't get access to the configured graph instances from the GremlinServer object and I'm not sure I'd change that as I'm not completely sure that this is a feature that would be useful to everyone. 目前你不能从GremlinServer对象访问配置的图形实例,我不确定我是否会改变它,因为我不完全确定这是一个对每个人都有用的功能。

It looks to me like what you need is a way to "initialize" your Graph instance. 在我看来,你需要的是一种“初始化” Graph实例的方法。 If so, then Gremlin Server offers a way to do that. 如果是这样,那么Gremlin Server提供了一种方法。 You can supply an initialization script in the yaml file (the below is a snippet from conf/gremlin-server-classic.yaml which is packaged with Gremlin Server distribution). 您可以在yaml文件中提供初始化脚本(以下是来自conf/gremlin-server-classic.yaml的片段,它与Gremlin Server发行版一起打包)。

scriptEngines: {
  gremlin-groovy: {
    imports: [java.lang.Math],
    staticImports: [java.lang.Math.PI],
    scripts: [scripts/generate-classic.groovy]}}

Note the "scripts" key which lets you supply script files to execute. 请注意“脚本”键,它允许您提供要执行的脚本文件。 Those scripts will yield you access to "g" (or whatever graphs you have configured). 这些脚本将使您可以访问“g”(或您配置的任何图形)。 For this example, scripts/generate-classic.groovy just has: 对于此示例, scripts/generate-classic.groovy只有:

TinkerFactory.generateClassic(g)

In this way you can do all your initialization work on the Graph that will ultimately be hosted by Gremlin Server when it starts and can then simply start it all up in the standard way with bin/gremlin-server.sh . 通过这种方式,您可以在Graph上完成所有初始化工作,这些工作最终将由Gremlin Server在启动时托管,然后可以使用bin/gremlin-server.sh以标准方式启动它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM