我正在尝试将一些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
的简单示例谢谢!
答案 0 :(得分:3)
2016年1月更新
在评论中,您会注意到有关neo4j的某些事情正在发生变化。我认为这个答案的其余部分仍然有效,但是如果你是一个时间旅行者在2016年中期来到这个职位,那么看一下新的neo4j二进制协议(AFAIK,称为“bolt”)是否可用。 / p>
<强> / ENDUPDATE 强>
坏消息是不推荐使用包装neo server boostrapper,我认为没有使用弃用方法的方法可以做到这一点。所以对你的问题的简单回答是“不”。
也许一年前,我一直在寻找与你相同的东西,但是让我分享一下我在此期间学到的可能改变你问题的东西。
因此,当您使用嵌入式服务器时,您会获得某些优势,例如使用Java API的能力,但是您会遇到一些很大的缺点。将DB放在与应用程序相同的内存空间中意味着您必须在两者之间兼顾内存。这意味着您无法在不停止数据库的情况下升级应用程序。
当您使用服务器时,许多事情更好,比如能够在不经过您的应用层,使用RESTful服务等的情况下运行密码。
WrappingNeoServerBootstrapper的问题(以及为什么它被弃用可能是好的)是它有两种方法的缺点。当然,您获得了REST服务和密码,但您仍然与应用程序处于相同的内存空间。
在架构上,我们在neo4j中发现的是,您通常只想使用外部独立服务器,然后通过REST服务与之通信。我认为neo4j正在研究二进制协议(ala JDBC,但当然不是同一个东西),因此可能会打开更多的Java API并提高性能。与此同时,neo4j的所有优秀库(包括spring-data和其他)都可以与HTTP端点通信,因此它们提供的任何功能通常都可以通过单独的服务器完成。对于应用程序的可维护性和neo4j本身的可调整性,您几乎总是会更好地运行单独的服务器。
请注意,此建议模仿了您对几乎所有其他类型的数据库(mongo,oracle,无论如何)所看到的内容。有些为小型/专用应用程序提供了嵌入式选项,但几乎所有应用程序都假设您将运行单独的服务器进程并让您的应用程序与之通信。所以这根本不是图表,只是关于良好的应用程序设计,可演化性和可维护性。
因此,出于这些原因,不推荐使用WrappingNeoServerBootstrapper(可能不会再回来)。我的经验表明,这不是你应该做的事情。
答案 1 :(得分:3)
你总是可以这样做。不是将您创建的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);
答案 2 :(得分:2)
使用Neo4J 3.1.1和czajah的方法,&#34;嵌入式&#34;模式确实可以很好地启动(没有弃用的调用),以及操作来自同一JVM实例的图形数据的优点。
以下示例代码需要neo4j
组中的依赖项工件neo4j-server
和org.neo4j
。省略了服务器配置文件,同时指定了工作存储文件夹和合适的配置选项,以便neo4j console
和neo4j-shell
(已被弃用而不是cypher-shell)可以用于&# 34;嵌入式&#34;实例
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);
}
}
答案 3 :(得分:1)
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 config
<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]} - {}
免责声明:我认为适当的架构涉及一组服务器模式螺栓启用的Neo4j服务器,使用筏协议下的因果聚类。 这个未记录的/内部API用作临时解决方法,以便在3.1.0中的嵌入式Neo4j服务器上启动neo4j浏览器,因为它曾在2.3中的WrappingNeoServerBootstrapper下工作。使用嵌入式服务器进行更快的遍历就是用例 - 必须重新评估性能,以确定基于螺栓的体系结构是否更适合遍历API。 /迈克尔