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还是很重要的。


猜你喜欢

转载自kevin-li.iteye.com/blog/1522169