XQuery/eXist 复制
本文件已过时,应更新或删除。
请查看 GitHub 上的页面以获取最新信息。
您希望配置两个或多个 eXist 实例,以便它们协同工作,自动同步特定于集合的数据集。这使您可以扩展 eXist 服务器的容量。例如,通过配置多个 eXist 服务器以同步,如以下所述,您可以添加负载均衡器以在服务器池中分配传入查询的负载,同时仍保持高性能。
我们将使用 eXist-db 2.1dev(最新版本)开发版中独有的新 eXist 集群选项。此功能基于使用集合触发器来触发来自主服务器到一个或多个远程主机上的从系统的“更新”消息。
注意:此页面正在开发中。
从长远来看,eXist 集群系统可能会有很多不同的配置方式。在本教程中,我们将仅介绍从单个主服务器到多个从系统的基于集合的复制。下图描述了此复制配置中节点之间的关系。
我们将在此文件中使用以下术语
- 主服务器 - 特别配置的 eXist 实例,在该实例中对文档和集合进行活动更改。例如,XML 更新、文档正在存储、更新或删除。主服务器被认为是更改事件的“发布者”。这也必须是运行 ActiveMQ 服务器的服务器。
- 从服务器 - 一组一个或多个特别配置的 eXist 实例,当主服务器发生更改时,它们会自动接收更新。每个从服务器被认为是主服务器上更改事件的“订阅者”。
- 消息存储 - 主服务器 eXist 实例外部的位置,用于存储所有更新事件,并在远程系统准备好接收更新事件时将这些事件转发到远程系统。尽管在我们的例子中经常使用术语“消息队列”,但我们将使用“主题”,而不是“队列”,来将消息分发到远程系统。ActiveMQ 在主服务器上提供此功能。
当配置的集合上的任何文档发生更改时,更新将被放置到消息队列中。更新将保留在该消息队列中,直到所有订阅者都收到更新消息。
注意:需要与开发人员确认:任何系统上的任何集合都可以被配置为主服务器或从服务器,以其他系统上的其他集合。
注意:一旦“持久”消息实现,从系统就不需要在更改时运行。当从服务器关闭时,它会自动收到自上次与主服务器通信以来的所有更改通知。
集群复制配置使用基于 Java 消息系统标准 (JMS) 的标准兼容消息系统。eXist 使用的实现基于 Apache ActiveMQ 系统。ActiveMQ 广泛用作“中间件”来帮助应用程序以可靠的方式进行通信。
- 从 https://activemq.apache.ac.cn/download.html 下载 ActiveMQ 的最新版本。请注意,TGZ 文件具有额外的 Unix(Linux、Mac OS X)支持,ZIP 文件适用于 Windows。
- 将内容解压缩到磁盘,称为 $ACTIVEMQ_HOME
- 将 $ACTIVEMQ_HOME/activemq-all-X.Y.Z.jar 文件复制到 $EXIST_HOME/lib/user
为了测试,我使用了 activemq-all-5.6.0.jar。
注意:集群的当前工作是在 eXist-db 子版本库的分支中完成的。要构建此分支,请使用子版本客户端检出以下 URL
https://exist.svn.sourceforge.net/svnroot/exist/branches/dizzzz/clustering
此代码将在将来某个时间点移入主干。
请注意,extensions/local.properties 中包含以下行,该行尚未在主干中
# Clustering extenstion for reliable document replication include.feature.clustering = true
然后,您可以使用 $EXIST_HOME/build.sh 或 build.bat 构建 eXist。
构建完成后,您将看到以下文件
$EXIST_HOME/lib/extensions/exist-clustering.jar
为必须分发其内容的目录添加一个 collection.xconf 文件,例如,对于 /db/mycollection/,.xconf 文件必须存储在 /db/system/config/db/mycollection/ 中。
创建集合 '/db/mycollection'
填写 activemq 消息代理的主机名(此处为“server.local:61616”)。
文件:/db/system/config/db/mycollection/collection.xconf
<collection xmlns="http://exist-db.org/collection-config/1.0">
<triggers>
<trigger class="org.exist.replication.jms.publish.ReplicationTrigger">
<parameter name="java.naming.factory.initial" value="org.apache.activemq.jndi.ActiveMQInitialContextFactory"/>
<parameter name="java.naming.provider.url" value="tcp://127.0.0.1:61616"/>
<parameter name="connectionfactory" value="ConnectionFactory"/>
<parameter name="destination" value="dynamicTopics/eXistdb"/>
<parameter name="client-id" value="id1"/>
</trigger>
</triggers>
</collection>
在下面的示例中,集合名为“mycollection”
对于每个“从服务器”,必须通过 conf.xml 启动作业;作业名称必须与“主服务器”配置的作业名称匹配
<!--
Start JMS listener for clustering feature.
Parameters:
java.naming.factory.initial Initial context provider
java.naming.provider.url URL of message broker
connectionfactory Name of connection factory
destination Name of destination (Topic or Queue)
client.id (optional) ClientID. Leave out or set ""
for default behaviour
-->
<job type="startup" name="clustering" class="org.exist.replication.jms.subscribe.MessageReceiverJob">
<parameter name="java.naming.factory.initial" value="org.apache.activemq.jndi.ActiveMQInitialContextFactory"/>
<parameter name="java.naming.provider.url" value="tcp://127.0.0.1:61616"/>
<parameter name="connectionfactory" value="ConnectionFactory"/>
<parameter name="destination" value="dynamicTopics/eXistdb"/>
<parameter name="client-id" value="id2"/>
<parameter name="subscriber-name" value="sub_name"/>
</job>
启动 ActiveMQ 服务器
cd ACTIVEMQ_HOME ./bin/activemq start (for mac, use the bin/macosx wrapper)
在每个从服务器上启动 eXist,并创建将镜像从服务器的集合
cd EXISTSLAVE_HOME ./bin/startup.sh Create receive collection '/db/mycollection'
启动主服务器
cd EXISTMASTER_HOME ./bin/startup.sh (No need to create the collection, since we already created above)
当使用动态主题或动态队列时,您可以通过访问 https://127.0.0.1:8161/admin/topics.jsp 来查看主服务器或从服务器是否已检查队列。请记得使用 F5 键刷新页面。
在“主服务器”上,在 /db/mycollection/ 中创建文档(例如,使用 Java 客户端或 eXide;以管理员身份登录)。该文档将自动复制到系统中的所有从服务器。
使用 eXide,我们可以将一个约 50k 的 XML 文档上传到从服务器,例如,/db/mydoc.xml。然后,当我们执行以下查询时,服务器上将创建 2000 个文件(mydoc1000.xml 到 mydoc3000.xml),并复制到从服务器。
let $doc := doc('/db/mydoc.xml') for $i in (1000 to 3000) return xmldb:store('/db/mycollection', concat('mydoc', $i , ".xml"), $doc)
将 Log4j 系统配置为调试模式。
在主服务器系统上,您应该看到以下行
2012-06-19 13:26:43,406 [eXistThread-90] DEBUG (Collection.java [storeXMLInternal]:1339) - document stored. 2012-06-19 13:26:43,406 [eXistThread-90] DEBUG (ClusterTrigger.java [afterCreateDocument]:63) - /db/mycollection/mydoc1000.xml 2012-06-19 13:26:43,406 [eXistThread-90] DEBUG (NativeSerializer.java [serializeToReceiver]:112) - serializing document 1430 (/db/mycollection/mydoc1000.xml) to SAX took 0 msec 2012-06-19 13:26:43,419 [eXistThread-90] DEBUG (JMSMessageSender.java [sendMessage]:156) - Message sent with id: ID:Dan-PC12-51166-1340109804913-3:1:1:1:1
在从服务器系统上,您应该看到以下内容
2012-06-19 13:48:05,875 [DefaultQuartzScheduler_Worker-2] DEBUG (NotificationService.java [debug]:94) - Registered UpdateListeners: 2012-06-19 13:50:06,218 [ActiveMQ Session Task-1] DEBUG (eXistJMSListener.java [onMessage]:138) - CREATE_UPDATE : DOCUMENT from /db/mycollection/mydoc1000.xml 2012-06-19 13:50:06,234 [ActiveMQ Session Task-1] DEBUG (ConfigurationHelper.java [getExistHome]:55) - Got eXist home from broker: C:\ws\exist-trunk\eXist
由于消息传递是一种在计算机系统之间进行通信的通用方法,因此可以通过这种第一个示例的变体来解决许多其他可能的业务问题。复制不仅可以提高可靠性,而且还可以与负载平衡和自动扩展一起使用,在系统负载过重时提高性能。
消息还可以用于将查询分配到多个节点,每个节点都有自己的数据集合。查询结果被放置在结果队列中,并返回给用户,就好像他们正在使用单个非常快的服务器一样。
由于主 eXist 系统只需要将更新事件放置在消息队列上,因此您可以自由地使用各种配置的消息存储来将数据和程序分发到具有不同可靠性级别的远程站点。
创建消息队列有两种选择
- 静态 您可以在 ActiveMQ 的配置文件中定义必须创建的主题或队列
- 动态 队列可以在您第一次使用它们时创建
- Subversion 中的密钥集群自述文件
- Apache Active MQ - 集群工具使用的 Apache ActiveMQ 软件的主页
- ActiveMQ In Action - 使用 ActiveMQ 的良好概述书籍