替换已弃用的`WrappingNeoServerBootstrapper`
Replacement for deprecated `WrappingNeoServerBootstrapper`
我正在尝试将一些 Neo4J Java 代码转换为 2.2+,该代码运行带有 Web 前端的嵌入式 Neo4J 服务器。
// configure embedded DB,
// but this doesn't start a server at port 12345 ?
final GraphDatabaseService db = new GraphDatabaseFactory()
.newEmbeddedDatabaseBuilder("/path/to/db")
.setConfig(ServerSettings.webserver_address, "localhost")
.setConfig(ServerSettings.webserver_port, 12345)
.newGraphDatabase();
// add shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override public void run() {
graphDb.shutdown();
}
});
启动服务器的已弃用代码如下:
final GraphDatabaseAPI api = (GraphDatabaseAPI)db;
final ServerConfigurator c = new ServerConfigurator(api);
c.configuration().addProperty(
Configurator.WEBSERVER_ADDRESS_PROPERTY_KEY, "localhost");
c.configuration().addProperty(
Configurator.WEBSERVER_PORT_PROPERTY_KEY, 12345);
new WrappingNeoServerBootstrapper(api, c).start();
离开这个不会启动服务器。我不清楚如何在不使用已弃用方法的情况下获得嵌入式服务器 运行。有什么想法吗?
更新:
看来确实是正确答案:改变你的架构。
不应该再使用嵌入式服务器,而是使用服务器和 RESTful API。对于您需要 Java API 的位,您可以编写一个非托管扩展(参见 docs)。
这里有一个这样的扩展的简单例子https://github.com/histograph/neo4j-plugin
谢谢!
2016 年 1 月更新
在评论中,您会注意到关于 neo4j 的某些事情正在发生变化。我认为这个答案的其余部分仍然有效,但如果你是 2016 年中期来到这个 post 的时间旅行者,请查看新的 neo4j 二进制协议(AFAIK,称为 "bolt") 可用。
/结束更新
坏消息是包装 neo 服务器 boostrapper 已被弃用,我认为没有使用弃用方法的方法可以做到这一点。所以你的问题的简单答案是 "no".
也许一年前,我一直在寻找与您相同的东西,但让我分享一下我在此期间学到的东西,这可能会改变您的问题。
因此,当您使用嵌入式服务器时,您会获得某些优势,例如能够使用 java API,但您也会遇到一些很大的劣势。将数据库放在与您的应用程序相同的内存 space 中意味着您必须在两者之间兼顾内存。这意味着您不能在不停止数据库的情况下升级您的应用程序。
当您使用服务器时,许多事情会变得更好,例如无需通过应用程序层即可 运行 加密的能力、使用 RESTful 服务等。
WrappingNeoServerBootstrapper 的问题(以及为什么弃用它可能是件好事)是它具有两种方法的缺点。当然,您获得了 REST 服务和密码,但您仍然在与应用程序相同的内存中 space。
从架构上讲,我们在 neo4j 中发现的是,您通常只想使用外部独立服务器,然后通过 REST 服务与其通信。我认为 neo4j 正在研究二进制协议(ala JDBC 但当然不是同一件事),因此可能会打开更多 java API 并且性能会提高。与此同时,neo4j 的所有优秀库,包括 spring-data 和其他库都可以与 HTTP 端点通信,因此它们提供的任何功能通常都可以通过单独的服务器完成。为了应用程序的可维护性和 neo4j 本身的可调整性,您几乎总是 运行 使用单独的服务器会更好。
请注意,此建议模仿了您在几乎所有其他类型的数据库(mongo、oracle 等)中看到的情况。有些为 small/specialized 应用程序提供嵌入式选项,但几乎所有这些都假设您将 运行 一个单独的服务器进程并让您的应用程序与之对话。所以这根本不是关于图表,只是关于良好的应用程序设计、可演化性和可维护性。
因此,由于这些原因,WrappingNeoServerBootstrapper 被弃用(并且可能不会回来)是可以的。我的经验表明这不是你真正应该做的事情。
你总是可以反过来做。不要将您创建的 GraphDatabaseService 实例传递给服务器,而是先尝试启动服务器并检索由它创建的实例:)已检查 3.0.6
String homeDir = "./";
String configFile = "./conf/neo4j.conf";
ServerBootstrapper serverBootstrapper = new CommunityBootstrapper();
int i = serverBootstrapper.start(new File(homeDir), Optional.of(new File(configFile)), Pair.of("dbms.connector.http.address","0.0.0.0:7575"));
NeoServer neoServer = serverBootstrapper.getServer();
GraphDatabaseService graph = neoServer.getDatabase().getGraph();
System.out.println(graph);
Czajah,您好,您的 3.0.6 解决方法也适用于生产嵌入式模式(较旧的 paxos HA)3.1.0 - 谢谢。
来源
github 项目(Maven,Tomcat 8 WAR)在 https://github.com/obrienlabs/nbi-neo4j-embedded-aws-war
端点
向嵌入式图数据库添加一个节点
http://neo4j.ca-central-1.elasticbeanstalk.com/FrontController?action=graph
浏览器在端口 7575
通过一些修改,我能够使用 EnterpriseBootstrapper 包装 HighlyAvailableGraphDatabase。
debug.log 中的 JMX 报告有一些非致命异常可能与我的 8.0.28 tomcat 版本有关,但 Tomcat 中嵌入的图形数据库 运行可以。
2016-12-21 16:20:00.574+0000 INFO Bolt enabled on 0.0.0.0:7688.
2016-12-21 16:20:09.554+0000 INFO Attempting to join cluster of [127.0.0.1:5001]
2016-12-21 16:20:11.566+0000 INFO Creating new cluster with name [neo4j.ha]...
2016-12-21 16:20:11.607+0000 INFO Instance 1 (this server) entered the cluster
2016-12-21 16:20:12.164+0000 INFO I am 1, moving to master
2016-12-21 16:20:12.293+0000 INFO Instance 1 (this server) was elected as coordinator
2016-12-21 16:20:12.462+0000 INFO I am 1, successfully moved to master
2016-12-21 16:20:12.513+0000 INFO Instance 1 (this server) is available as master at ha://127.0.0.1:6001?serverId=1 with StoreId{creationTime=1482199697648, randomId=7800059877674392627, storeVersion=15531981201765894, upgradeTime=1482199697648, upgradeId=1}
2016-12-21 16:20:14.495+0000 INFO Database available for write transactions
2016-12-21 16:20:31.917+0000 INFO Mounted REST API at: /db/manage
2016-12-21 16:20:53.264+0000 INFO Remote interface available at http://localhost:7575/
register: org.obrienlabs.nbi.graph.service.HaMonitor@1c0f80c9
public class ExtendedHighlyAvailableGraphDatabaseFactory extends HighlyAvailableGraphDatabaseFactory {
private Log log = LogFactory.getLog(ExtendedHighlyAvailableGraphDatabaseFactory.class);
private HaMonitor haMonitor;
@Override
public GraphDatabaseService newDatabase( final Map<String, String> config ) {
EnterpriseBootstrapper serverBootstrapper = new EnterpriseBootstrapper();
List<Pair> pairs = new ArrayList<>();
for(Entry<String, String> entry : config.entrySet()) {
pairs.add(Pair.of(entry.getKey(), entry.getValue()));
}
Pair pairArray[] = new Pair[pairs.size()];
// will resolve to /dir/data/databases/graph.db
serverBootstrapper.start(storeDir, Optional.empty(), pairs.toArray(pairArray));
GraphDatabaseService graph = serverBootstrapper.getServer().getDatabase().getGraph();
// set the paxos HA listener only when dbms.mode=HA
if(graph instanceof HighlyAvailableGraphDatabase) {
haMonitor.setDb((HighlyAvailableGraphDatabase) graph);
HighAvailabilityMemberStateMachine memberStateMachine =
((HighlyAvailableGraphDatabase)graph).getDependencyResolver()
.resolveDependency(HighAvailabilityMemberStateMachine.class);
if ( memberStateMachine != null ) {
memberStateMachine.addHighAvailabilityMemberListener(haMonitor);
log.info("register: " + haMonitor);
}
}
return graph;
} };
}
Spring 配置
<util:map id="config">
<entry key="ha.server_id" value="1"/>
<entry key="ha.initial_hosts" value="127.0.0.1:5001"/>
<entry key="dbms.mode" value="HA"/>
<entry key="browser.allow_outgoing_connection" value="true" />
<entry key="unsupported.dbms.ephemerall" value="false" />
<entry key="dbms.connector.http.address" value="0.0.0.0:7575" />
<entry key="dbms.connector.bolt.address" value="0.0.0.0:7688" />
<entry key="dbms.connector.http.enabled" value="true" />
<entry key="dbms.connector.bolt.enabled" value="true" />
<entry key="dbms.connector.http.type" value="HTTP" />
<entry key="dbms.connector.bolt.type" value="BOLT" />
<entry key="dbms.connector.http.tls_level" value="DISABLED" />
<entry key="dbms.connector.bolt.tls_level" value="DISABLED" />
<entry key="dbms.security.auth_enabled" value="true"/>
<entry key="dbms.logs.debug.level" value="DEBUG"/>
<entry key="dbms.logs.http.enabled" value="true" />
<entry key="dbms.logs.query.enabled" value="true"/>
<entry key="dbms.shell.enabled" value="true"/>
</util:map>
<bean id="haMonitor" class="org.obrienlabs.nbi.graph.service.HaMonitor"/>
<bean id="graphDbFactory" class="org.obrienlabs.nbi.graph.service.ExtendedHighlyAvailableGraphDatabaseFactory">
<constructor-arg ref="haMonitor" />
</bean>
<bean id="graphDbBuilder"
factory-bean="graphDbFactory"
factory-method="newEmbeddedDatabaseBuilder">
<constructor-arg value="/ec2-user"/>
</bean>
<bean id="graphDbBuilderFinal"
factory-bean="graphDbBuilder"
factory-method="setConfig">
<constructor-arg ref="config"/>
</bean>
<!-- HighlyAvailableGraphDatabase wrapped by an EnterpriseBootstrapper NeoServer created in this constructor -->
<bean id="graphDatabaseService"
factory-bean="graphDbBuilderFinal"
factory-method="newGraphDatabase"
destroy-method="shutdown" />
交易完成
2016-12-21 20:51:07.478+0000 INFO [o.n.k.i.s.c.CountsTracker] About to rotate counts store at transaction 9 to [/ec2-user/data/databases/graph.db/neostore.counts.db.b], from [/ec2-user/data/databases/graph.db/neostore.counts.db.a].
2016-12-21 20:51:07.480+0000 INFO [o.n.k.i.s.c.CountsTracker] Successfully rotated counts store at transaction 9 to [/ec2-user/data/databases/graph.db/neostore.counts.db.b], from [/ec2-user/data/databases/graph.db/neostore.counts.db.a].
2016-12-21 20:51:07.483+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Check Pointing triggered by scheduler for time threshold [9]: Store flush completed
jconsole 中 mbean 的设置是
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] Kernel version: 3.1.0,16a782b42d76ca37db72958eb2565cf6aa671a29
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] Neo4j Kernel properties:
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.logs.query.enabled=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.security.auth_enabled=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.bolt.tls_level=DISABLED
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.shell.enabled=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] ha.server_id=1
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.logs.http.enabled=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] ha.initial_hosts=127.0.0.1:5001
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.allow_format_migration=false
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.http.address=0.0.0.0:7575
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.bolt.enabled=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.http.tls_level=DISABLED
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.http.enabled=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.mode=HA
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.block_size.labels=56
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.bolt.type=BOLT
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.directories.neo4j_home=/ec2-user
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.ephemerall=false
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] browser.allow_outgoing_connection=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.logs.debug.level=DEBUG
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.http.type=HTTP
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.block_size.strings=120
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.block_size.array_properties=120
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.edition=enterprise
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.bolt.address=0.0.0.0:7688
7575(码头服务器)和 7688(螺栓)端口已打开
obrienlabs-mbp15:_deployment michaelobrien$ netstat -vatn | grep 7575
tcp46 0 0 *.7575 *.* LISTEN 131072 131072 49013 0
tcp4 0 0 127.0.0.1.7575 127.0.0.1.60685 TIME_WAIT 407296 146988 49013 0
tcp6 0 0 ::1.7575 ::1.60699 TIME_WAIT 407284 146808 49013 0
tcp6 0 0 ::1.7575 ::1.60700 TIME_WAIT 407284 146808 49013 0
obrienlabs-mbp15:_deployment michaelobrien$ netstat -vatn | grep 7688
tcp6 0 0 ::1.7688 ::1.60704 ESTABLISHED 406582 146808 49013 0
tcp6 0 0 ::1.60704 ::1.7688 ESTABLISHED 398196 146808 48165 0
tcp6 0 0 ::1.7688 ::1.60702 ESTABLISHED 406570 146808 49013 0
tcp6 0 0 ::1.60702 ::1.7688 ESTABLISHED 398185 146808 48165 0
tcp6 0 0 ::1.7688 ::1.60701 ESTABLISHED 407255 146808 49013 0
tcp6 0 0 ::1.60701 ::1.7688 ESTABLISHED 407628 146808 48165 0
tcp46 0 0 *.7688 *.* LISTEN 131072 131072 49013 0
obrienlabs-mbp15:_deployment michaelobrien$ netstat -vatn | grep 8080
tcp4 0 0 127.0.0.1.8080 127.0.0.1.60584 FIN_WAIT_2 408104 146988 49013 0
tcp4 994 0 127.0.0.1.60584 127.0.0.1.8080 CLOSE_WAIT 408128 146988 42992 0
tcp46 0 0 *.8080 *.* LISTEN 131072 131072 49013 0
udp4 0 0 *.* *.* 196724 9216 38080 0
/ec2-user/logs/http.log
2016-12-23 02:53:21.505+0000 INFO [REQUEST] [AsyncLog @ 2016-12-23 02:53:21.505+0000] 0:0:0:0:0:0:0:1 - [Thu Dec 22 21:53:21 EST 2016] "/browser/views/frame-cypher.html?null" 200 22972 "http://localhost:7575/browser/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14" 2
query.log
2016-12-23 13:33:39.059+0000 INFO 175 ms: bolt-session bolt neo4j neo4j-javascript/[object Object] client/0:0:0:0:0:0:0:1:64019 server/0:0:0:0:0:0:0:1:7688> neo4j - MATCH (a)-[r]->(b) WHERE id(a) IN {node_ids}
AND id(b) IN {new_node_ids}
RETURN r; - {node_ids: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], new_node_ids: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]} - {}
免责声明:我相信一个合适的架构涉及一组集群的服务器模式 bolt 启用 Neo4j 服务器使用 raft 协议下的因果集群。
此 undocumented/internal API 用作临时解决方法,以在 3.1.0 中的嵌入式 Neo4j 服务器上启动 neo4j 浏览器,因为它曾在 2.3 中的 WrappingNeoServerBootstrapper 下工作。使用嵌入式服务器实现更快的遍历是用例 - 必须重新评估性能以确定基于螺栓的架构是否更适合遍历 API。
/迈克尔
使用 Neo4J 3.1.1 和 的方法,"embedded" 模式真的可以很好地启动(没有弃用的调用),以及从相同的操作图形数据的优势JVM 实例。
下面的示例代码需要来自 org.neo4j
组的依赖项工件 neo4j
和 neo4j-server
。省略了服务器配置文件,同时指定了工作存储文件夹和合适的配置选项,以便 neo4j console
和 neo4j-shell
(已被弃用,取而代之的是 cypher-shell)可以用于 "embedded"实例.
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.helpers.collection.Pair;
import org.neo4j.server.CommunityBootstrapper;
import org.neo4j.server.NeoServer;
import org.neo4j.server.ServerBootstrapper;
import java.io.File;
import java.io.IOException;
import java.util.Optional;
public class RunNeoRun {
public static void main(String[] args) throws IOException {
// Wherever the Neo4J storage location is.
File storeDir = new File("/tmp/tmp4j");
ServerBootstrapper serverBootstrapper = new CommunityBootstrapper();
serverBootstrapper.start(
storeDir,
Optional.empty(), // omit configfile, properties follow
Pair.of("dbms.connector.http.address","127.0.0.1:7474"),
Pair.of("dbms.connector.http.enabled", "true"),
Pair.of("dbms.connector.bolt.enabled", "true"),
// allow the shell connections via port 1337 (default)
Pair.of("dbms.shell.enabled", "true"),
Pair.of("dbms.shell.host", "127.0.0.1"),
Pair.of("dbms.shell.port", "1337")
);
// ^^ serverBootstrapper.start() also registered shutdown hook!
NeoServer neoServer = serverBootstrapper.getServer();
GraphDatabaseService gdb = neoServer.getDatabase().getGraph();
/* Some transactional code */
try(Transaction tx = gdb.beginTx()) {
gdb.getAllNodes().forEach(
n -> System.out.println(n)
);
tx.success();
}
System.out.println("Press ENTER to quit.");
System.in.read();
System.exit(0);
}
}
我正在尝试将一些 Neo4J Java 代码转换为 2.2+,该代码运行带有 Web 前端的嵌入式 Neo4J 服务器。
// configure embedded DB,
// but this doesn't start a server at port 12345 ?
final GraphDatabaseService db = new GraphDatabaseFactory()
.newEmbeddedDatabaseBuilder("/path/to/db")
.setConfig(ServerSettings.webserver_address, "localhost")
.setConfig(ServerSettings.webserver_port, 12345)
.newGraphDatabase();
// add shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override public void run() {
graphDb.shutdown();
}
});
启动服务器的已弃用代码如下:
final GraphDatabaseAPI api = (GraphDatabaseAPI)db;
final ServerConfigurator c = new ServerConfigurator(api);
c.configuration().addProperty(
Configurator.WEBSERVER_ADDRESS_PROPERTY_KEY, "localhost");
c.configuration().addProperty(
Configurator.WEBSERVER_PORT_PROPERTY_KEY, 12345);
new WrappingNeoServerBootstrapper(api, c).start();
离开这个不会启动服务器。我不清楚如何在不使用已弃用方法的情况下获得嵌入式服务器 运行。有什么想法吗?
更新:
看来确实是正确答案:改变你的架构。
不应该再使用嵌入式服务器,而是使用服务器和 RESTful API。对于您需要 Java API 的位,您可以编写一个非托管扩展(参见 docs)。
这里有一个这样的扩展的简单例子https://github.com/histograph/neo4j-plugin
谢谢!
2016 年 1 月更新
在评论中,您会注意到关于 neo4j 的某些事情正在发生变化。我认为这个答案的其余部分仍然有效,但如果你是 2016 年中期来到这个 post 的时间旅行者,请查看新的 neo4j 二进制协议(AFAIK,称为 "bolt") 可用。
/结束更新
坏消息是包装 neo 服务器 boostrapper 已被弃用,我认为没有使用弃用方法的方法可以做到这一点。所以你的问题的简单答案是 "no".
也许一年前,我一直在寻找与您相同的东西,但让我分享一下我在此期间学到的东西,这可能会改变您的问题。
因此,当您使用嵌入式服务器时,您会获得某些优势,例如能够使用 java API,但您也会遇到一些很大的劣势。将数据库放在与您的应用程序相同的内存 space 中意味着您必须在两者之间兼顾内存。这意味着您不能在不停止数据库的情况下升级您的应用程序。
当您使用服务器时,许多事情会变得更好,例如无需通过应用程序层即可 运行 加密的能力、使用 RESTful 服务等。
WrappingNeoServerBootstrapper 的问题(以及为什么弃用它可能是件好事)是它具有两种方法的缺点。当然,您获得了 REST 服务和密码,但您仍然在与应用程序相同的内存中 space。
从架构上讲,我们在 neo4j 中发现的是,您通常只想使用外部独立服务器,然后通过 REST 服务与其通信。我认为 neo4j 正在研究二进制协议(ala JDBC 但当然不是同一件事),因此可能会打开更多 java API 并且性能会提高。与此同时,neo4j 的所有优秀库,包括 spring-data 和其他库都可以与 HTTP 端点通信,因此它们提供的任何功能通常都可以通过单独的服务器完成。为了应用程序的可维护性和 neo4j 本身的可调整性,您几乎总是 运行 使用单独的服务器会更好。
请注意,此建议模仿了您在几乎所有其他类型的数据库(mongo、oracle 等)中看到的情况。有些为 small/specialized 应用程序提供嵌入式选项,但几乎所有这些都假设您将 运行 一个单独的服务器进程并让您的应用程序与之对话。所以这根本不是关于图表,只是关于良好的应用程序设计、可演化性和可维护性。
因此,由于这些原因,WrappingNeoServerBootstrapper 被弃用(并且可能不会回来)是可以的。我的经验表明这不是你真正应该做的事情。
你总是可以反过来做。不要将您创建的 GraphDatabaseService 实例传递给服务器,而是先尝试启动服务器并检索由它创建的实例:)已检查 3.0.6
String homeDir = "./";
String configFile = "./conf/neo4j.conf";
ServerBootstrapper serverBootstrapper = new CommunityBootstrapper();
int i = serverBootstrapper.start(new File(homeDir), Optional.of(new File(configFile)), Pair.of("dbms.connector.http.address","0.0.0.0:7575"));
NeoServer neoServer = serverBootstrapper.getServer();
GraphDatabaseService graph = neoServer.getDatabase().getGraph();
System.out.println(graph);
Czajah,您好,您的 3.0.6 解决方法也适用于生产嵌入式模式(较旧的 paxos HA)3.1.0 - 谢谢。
来源
github 项目(Maven,Tomcat 8 WAR)在 https://github.com/obrienlabs/nbi-neo4j-embedded-aws-war
端点
向嵌入式图数据库添加一个节点 http://neo4j.ca-central-1.elasticbeanstalk.com/FrontController?action=graph
浏览器在端口 7575
通过一些修改,我能够使用 EnterpriseBootstrapper 包装 HighlyAvailableGraphDatabase。
debug.log 中的 JMX 报告有一些非致命异常可能与我的 8.0.28 tomcat 版本有关,但 Tomcat 中嵌入的图形数据库 运行可以。
2016-12-21 16:20:00.574+0000 INFO Bolt enabled on 0.0.0.0:7688.
2016-12-21 16:20:09.554+0000 INFO Attempting to join cluster of [127.0.0.1:5001]
2016-12-21 16:20:11.566+0000 INFO Creating new cluster with name [neo4j.ha]...
2016-12-21 16:20:11.607+0000 INFO Instance 1 (this server) entered the cluster
2016-12-21 16:20:12.164+0000 INFO I am 1, moving to master
2016-12-21 16:20:12.293+0000 INFO Instance 1 (this server) was elected as coordinator
2016-12-21 16:20:12.462+0000 INFO I am 1, successfully moved to master
2016-12-21 16:20:12.513+0000 INFO Instance 1 (this server) is available as master at ha://127.0.0.1:6001?serverId=1 with StoreId{creationTime=1482199697648, randomId=7800059877674392627, storeVersion=15531981201765894, upgradeTime=1482199697648, upgradeId=1}
2016-12-21 16:20:14.495+0000 INFO Database available for write transactions
2016-12-21 16:20:31.917+0000 INFO Mounted REST API at: /db/manage
2016-12-21 16:20:53.264+0000 INFO Remote interface available at http://localhost:7575/
register: org.obrienlabs.nbi.graph.service.HaMonitor@1c0f80c9
public class ExtendedHighlyAvailableGraphDatabaseFactory extends HighlyAvailableGraphDatabaseFactory {
private Log log = LogFactory.getLog(ExtendedHighlyAvailableGraphDatabaseFactory.class);
private HaMonitor haMonitor;
@Override
public GraphDatabaseService newDatabase( final Map<String, String> config ) {
EnterpriseBootstrapper serverBootstrapper = new EnterpriseBootstrapper();
List<Pair> pairs = new ArrayList<>();
for(Entry<String, String> entry : config.entrySet()) {
pairs.add(Pair.of(entry.getKey(), entry.getValue()));
}
Pair pairArray[] = new Pair[pairs.size()];
// will resolve to /dir/data/databases/graph.db
serverBootstrapper.start(storeDir, Optional.empty(), pairs.toArray(pairArray));
GraphDatabaseService graph = serverBootstrapper.getServer().getDatabase().getGraph();
// set the paxos HA listener only when dbms.mode=HA
if(graph instanceof HighlyAvailableGraphDatabase) {
haMonitor.setDb((HighlyAvailableGraphDatabase) graph);
HighAvailabilityMemberStateMachine memberStateMachine =
((HighlyAvailableGraphDatabase)graph).getDependencyResolver()
.resolveDependency(HighAvailabilityMemberStateMachine.class);
if ( memberStateMachine != null ) {
memberStateMachine.addHighAvailabilityMemberListener(haMonitor);
log.info("register: " + haMonitor);
}
}
return graph;
} };
}
Spring 配置
<util:map id="config">
<entry key="ha.server_id" value="1"/>
<entry key="ha.initial_hosts" value="127.0.0.1:5001"/>
<entry key="dbms.mode" value="HA"/>
<entry key="browser.allow_outgoing_connection" value="true" />
<entry key="unsupported.dbms.ephemerall" value="false" />
<entry key="dbms.connector.http.address" value="0.0.0.0:7575" />
<entry key="dbms.connector.bolt.address" value="0.0.0.0:7688" />
<entry key="dbms.connector.http.enabled" value="true" />
<entry key="dbms.connector.bolt.enabled" value="true" />
<entry key="dbms.connector.http.type" value="HTTP" />
<entry key="dbms.connector.bolt.type" value="BOLT" />
<entry key="dbms.connector.http.tls_level" value="DISABLED" />
<entry key="dbms.connector.bolt.tls_level" value="DISABLED" />
<entry key="dbms.security.auth_enabled" value="true"/>
<entry key="dbms.logs.debug.level" value="DEBUG"/>
<entry key="dbms.logs.http.enabled" value="true" />
<entry key="dbms.logs.query.enabled" value="true"/>
<entry key="dbms.shell.enabled" value="true"/>
</util:map>
<bean id="haMonitor" class="org.obrienlabs.nbi.graph.service.HaMonitor"/>
<bean id="graphDbFactory" class="org.obrienlabs.nbi.graph.service.ExtendedHighlyAvailableGraphDatabaseFactory">
<constructor-arg ref="haMonitor" />
</bean>
<bean id="graphDbBuilder"
factory-bean="graphDbFactory"
factory-method="newEmbeddedDatabaseBuilder">
<constructor-arg value="/ec2-user"/>
</bean>
<bean id="graphDbBuilderFinal"
factory-bean="graphDbBuilder"
factory-method="setConfig">
<constructor-arg ref="config"/>
</bean>
<!-- HighlyAvailableGraphDatabase wrapped by an EnterpriseBootstrapper NeoServer created in this constructor -->
<bean id="graphDatabaseService"
factory-bean="graphDbBuilderFinal"
factory-method="newGraphDatabase"
destroy-method="shutdown" />
交易完成
2016-12-21 20:51:07.478+0000 INFO [o.n.k.i.s.c.CountsTracker] About to rotate counts store at transaction 9 to [/ec2-user/data/databases/graph.db/neostore.counts.db.b], from [/ec2-user/data/databases/graph.db/neostore.counts.db.a].
2016-12-21 20:51:07.480+0000 INFO [o.n.k.i.s.c.CountsTracker] Successfully rotated counts store at transaction 9 to [/ec2-user/data/databases/graph.db/neostore.counts.db.b], from [/ec2-user/data/databases/graph.db/neostore.counts.db.a].
2016-12-21 20:51:07.483+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Check Pointing triggered by scheduler for time threshold [9]: Store flush completed
jconsole 中 mbean 的设置是
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] Kernel version: 3.1.0,16a782b42d76ca37db72958eb2565cf6aa671a29
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] Neo4j Kernel properties:
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.logs.query.enabled=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.security.auth_enabled=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.bolt.tls_level=DISABLED
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.shell.enabled=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] ha.server_id=1
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.logs.http.enabled=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] ha.initial_hosts=127.0.0.1:5001
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.allow_format_migration=false
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.http.address=0.0.0.0:7575
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.bolt.enabled=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.http.tls_level=DISABLED
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.http.enabled=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.mode=HA
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.block_size.labels=56
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.bolt.type=BOLT
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.directories.neo4j_home=/ec2-user
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.ephemerall=false
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] browser.allow_outgoing_connection=true
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.logs.debug.level=DEBUG
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.http.type=HTTP
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.block_size.strings=120
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.block_size.array_properties=120
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.edition=enterprise
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.bolt.address=0.0.0.0:7688
7575(码头服务器)和 7688(螺栓)端口已打开
obrienlabs-mbp15:_deployment michaelobrien$ netstat -vatn | grep 7575
tcp46 0 0 *.7575 *.* LISTEN 131072 131072 49013 0
tcp4 0 0 127.0.0.1.7575 127.0.0.1.60685 TIME_WAIT 407296 146988 49013 0
tcp6 0 0 ::1.7575 ::1.60699 TIME_WAIT 407284 146808 49013 0
tcp6 0 0 ::1.7575 ::1.60700 TIME_WAIT 407284 146808 49013 0
obrienlabs-mbp15:_deployment michaelobrien$ netstat -vatn | grep 7688
tcp6 0 0 ::1.7688 ::1.60704 ESTABLISHED 406582 146808 49013 0
tcp6 0 0 ::1.60704 ::1.7688 ESTABLISHED 398196 146808 48165 0
tcp6 0 0 ::1.7688 ::1.60702 ESTABLISHED 406570 146808 49013 0
tcp6 0 0 ::1.60702 ::1.7688 ESTABLISHED 398185 146808 48165 0
tcp6 0 0 ::1.7688 ::1.60701 ESTABLISHED 407255 146808 49013 0
tcp6 0 0 ::1.60701 ::1.7688 ESTABLISHED 407628 146808 48165 0
tcp46 0 0 *.7688 *.* LISTEN 131072 131072 49013 0
obrienlabs-mbp15:_deployment michaelobrien$ netstat -vatn | grep 8080
tcp4 0 0 127.0.0.1.8080 127.0.0.1.60584 FIN_WAIT_2 408104 146988 49013 0
tcp4 994 0 127.0.0.1.60584 127.0.0.1.8080 CLOSE_WAIT 408128 146988 42992 0
tcp46 0 0 *.8080 *.* LISTEN 131072 131072 49013 0
udp4 0 0 *.* *.* 196724 9216 38080 0
/ec2-user/logs/http.log
2016-12-23 02:53:21.505+0000 INFO [REQUEST] [AsyncLog @ 2016-12-23 02:53:21.505+0000] 0:0:0:0:0:0:0:1 - [Thu Dec 22 21:53:21 EST 2016] "/browser/views/frame-cypher.html?null" 200 22972 "http://localhost:7575/browser/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14" 2
query.log
2016-12-23 13:33:39.059+0000 INFO 175 ms: bolt-session bolt neo4j neo4j-javascript/[object Object] client/0:0:0:0:0:0:0:1:64019 server/0:0:0:0:0:0:0:1:7688> neo4j - MATCH (a)-[r]->(b) WHERE id(a) IN {node_ids}
AND id(b) IN {new_node_ids}
RETURN r; - {node_ids: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], new_node_ids: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]} - {}
免责声明:我相信一个合适的架构涉及一组集群的服务器模式 bolt 启用 Neo4j 服务器使用 raft 协议下的因果集群。 此 undocumented/internal API 用作临时解决方法,以在 3.1.0 中的嵌入式 Neo4j 服务器上启动 neo4j 浏览器,因为它曾在 2.3 中的 WrappingNeoServerBootstrapper 下工作。使用嵌入式服务器实现更快的遍历是用例 - 必须重新评估性能以确定基于螺栓的架构是否更适合遍历 API。 /迈克尔
使用 Neo4J 3.1.1 和
下面的示例代码需要来自 org.neo4j
组的依赖项工件 neo4j
和 neo4j-server
。省略了服务器配置文件,同时指定了工作存储文件夹和合适的配置选项,以便 neo4j console
和 neo4j-shell
(已被弃用,取而代之的是 cypher-shell)可以用于 "embedded"实例.
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.helpers.collection.Pair;
import org.neo4j.server.CommunityBootstrapper;
import org.neo4j.server.NeoServer;
import org.neo4j.server.ServerBootstrapper;
import java.io.File;
import java.io.IOException;
import java.util.Optional;
public class RunNeoRun {
public static void main(String[] args) throws IOException {
// Wherever the Neo4J storage location is.
File storeDir = new File("/tmp/tmp4j");
ServerBootstrapper serverBootstrapper = new CommunityBootstrapper();
serverBootstrapper.start(
storeDir,
Optional.empty(), // omit configfile, properties follow
Pair.of("dbms.connector.http.address","127.0.0.1:7474"),
Pair.of("dbms.connector.http.enabled", "true"),
Pair.of("dbms.connector.bolt.enabled", "true"),
// allow the shell connections via port 1337 (default)
Pair.of("dbms.shell.enabled", "true"),
Pair.of("dbms.shell.host", "127.0.0.1"),
Pair.of("dbms.shell.port", "1337")
);
// ^^ serverBootstrapper.start() also registered shutdown hook!
NeoServer neoServer = serverBootstrapper.getServer();
GraphDatabaseService gdb = neoServer.getDatabase().getGraph();
/* Some transactional code */
try(Transaction tx = gdb.beginTx()) {
gdb.getAllNodes().forEach(
n -> System.out.println(n)
);
tx.success();
}
System.out.println("Press ENTER to quit.");
System.in.read();
System.exit(0);
}
}