Hibernate Search + Spring + ActiveMQ
使用了Hibernate Search 之后,在集群的环境下,就需要牵扯到同步index文件的问题, 《Hibernate Search In action》 提到了两种方式,一种是同步更新,一种是异步更新,下面来分别说说这种更新试的使用及实现:
1. 同步方式
同步方式就是一个节点的更新能被其它的节点实时获得,最经典的方式就是各个节点都读写同一个文件夹,当然了,如果节点在不同的机器上,那就需要能够无验证网络访问这个文件夹。在节点比较少的情况下,这种情况可以很好的工作,如果节点很多,而且更新又比较频繁,这种情况可能会带来锁竞争及其它的一些问题。
如何实现:《Hibernate Search In action》提到的比较多的是NFS,这是种在UNIX系统中使用的文件共享技术。windows下面也有对应的实现,但是,在64位的windows下可能会遇到一些麻烦。因为我的系统是windows64位的,所以我选用了另外一种实现方式,如在windows环境下,有两台机器A 和 B, A设置一个共享文件夹admin, 但在访问的时候需要用户名和密码,这时候可以用下面的这行命令在B机器上运行一下
rundll32 netplwiz.dll,UsersRunDll
命令,然后将需要访问A机器的用户名和密码设在B机器上,就可以访问这个 共享文件夹时不需要userName和Passwd了。
2. 异步方式
在《Hibernate Search In action》中提及一种JMS方式,即对Index文件的更先方到一个JMS队列中,然后由一个master节点统一进行index, 其它slave节点定时去master节点同步被Index后的文件,从而达到同步文件的目的。因为是异步的,所以有新的数据会被延迟搜索出来的情况发生, 除此之外,因为使用了JSM,所以一种JMS技术需要被引入及维护,部署上也带来子一定的难度。但是相比较这些不足,这种方式比较稳定,当在节点比较多的环境下, 应该是作为首先的。下面来谈谈如何实现。
其实在下面这篇文章中已经讲了如果去实现这种做法:
分布式Hibernate search
但是按照文中的说法进行部署的时候,也遇到了一些小的问题,特在下面记录一下,以做为这篇文章的补充:
A. 上面这文章中提到,在你的环境中配置activemq.xml文件,然后使用如下的配置去启动,
<bean id="broker" class="org.apache.activemq.xbean.BrokerFactoryBean">
<property name="config" value="WEB-INF/activemq.xml" />
<property name="start" value="true" />
</bean>
我认为不可取,应该让activemq在一上单独的Server中运行。因为当MQ是嵌在你的Application中运行时,如果你的Application挂了,那Slave节点就不可以将数据写到Q中,这样就会有丢数据的可能,而放在一个单独了Server中,如果master挂了,slave还是可以将数据放到Q中的,当master重启之后,又可以接着处理,当然了,为了保险,可能MQ也需要做集群。如单独启动,需要将下面的配置放在{ActiveMQ_HOME}/conf/activemq.xml文件中:
<amq:broker brokerName="HibernateSearchBroker">
<amq:managementContext>
<amq:managementContext createConnector="false"/>
</amq:managementContext>
<amq:transportConnectors>
<amq:transportConnector uri="tcp://localhost:61616" />
</amq:transportConnectors>
</amq:broker>
<amq:queue name="queue/hibernatesearch" physicalName="hibernateSearchQueue" />
启动之后,手动创建一个Q,名字叫hibernateSearchQueue。
B. 所有的都配置好了之后,在运行的过程中,发现slave节点的message可以正常发送,Master节点也可以获取到这个message,但是就是index不正确,通过Debug才发现在取session的时候,出错了,但是没有报出来错误信息。Master节点都要包含一个类继承自AbstractJMSHibernateSearchController来处理message,需要实现getSession这个方法,一开始我的写法如下:
@Repository("hibernateSearchController")
@Tansactional
public class JMSHibernateSearchController extends AbstractJMSHibernateSearchController implements MessageListener {
@Autowired
private SessionFactory sessionFactory;
@Override
protected void cleanSessionIfNeeded(Session session) {}
@Override
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
}
后来无论如何都不能获取到,后来改成如下的方式,成功:
@Override
protected Session getSession() {
return sessionFactory.openSession();
}
有些时候能进行Debug还是很重要的。
推荐阅读
-
详解Spring Hibernate连接oracle数据库的配置
-
Spring+Hibernate+Struts(SSH)框架整合实战
-
struts2、hibernate、spring的工作原理[简明易懂]
-
javaweb各种框架组合案例(六):springboot+spring data jpa(hibernate)+restful
-
Intellij IDEA 2019 + Java Spring MVC + Hibernate学习笔记(1)
-
在spring中使用Hibernate5
-
Spring 整合 Hibernate 时启用二级缓存实例详解
-
浅谈jpa、hibernate与spring data jpa三者之间的关系
-
【原创】整合Spring4+Hibernate4+Struts2时NullPointerException问题解决
-
Struts2 Hibernate Spring 运行流程与部分机制