Hibernate Search(基于version3.4)--第三章Configuration

Configuration

 

3.1激活Hiberate Search与自动indexing功能

3.1.1激活Hibernate Search

Hibernate Core会自动探测是否应用激活Hibernate Search。如果想禁用Hibernate Search,把hibernate.search.autoregister_listeners配置为false。当然,即使hibernate.search.autoregister_listeners配置为true,但是没有任何一个实体被注解为@Indexed,Hibernate Search也不会运行任何东西。

 

3.1.2激活自动indexing

默认情况下,每次一个持久对象被插入,更新,删除通过hibernate,Hibernate Search都会更新index。当index是只读或批量更新index的时候,你可能想要禁用该功能。

 

禁用基于事件的indexing:

Properties代码 复制代码 收藏代码
  1. hibernate.search.indexing_strategy = manual
hibernate.search.indexing_strategy = manual

Note:在大多数情况下,JMS后端提供了最好解决方案,一个轻量级的基于事件系统保持跟踪index的所有的改变,和重量级的indexing处理由独立的机器完成。

 

3.2Directory的配置

在配置Directory之前,你需要明白每一个indexed实体对应着一个Lucene index(除了多个indexed实体对应相同的index)。index的名称由@Indexed注解中的index属性指定,如果没有index属性,默认为类的全限定名。

 

根据index的名称,使用前缀hibernate.search.<indexname>.可以为每个index配置不同的DirectoryProvider和配置其他不同的属性。另外hibernate.search.default.是保留名,用于定义所有index的默认属性。Example 3.2, “Configuring directory providers” 展示了怎么样使用hibernate.search.default.directory_provider去设置默认的directory provider为filesystem,设置hibernate.search.default.indexBase为默认的index基本目录。Rule的index使用了in-memory directory,因为默认的DirectoryProvider被hibernate.search.Rules.directory_provider覆盖了。

 

Example 3.1. Specifying the index name

Java代码 复制代码 收藏代码
  1. package org.hibernate.example;
  2. @Indexed
  3. public class Status { ... }
  4. @Indexed(index="Rules")
  5. public class Rule { ... }
  6. @Indexed(index="Actions")
  7. public class Action { ... }
package org.hibernate.example;
@Indexed
public class Status { ... }
@Indexed(index="Rules")
public class Rule { ... }
@Indexed(index="Actions")
public class Action { ... }

Example 3.2. Configuring directory providers

Properties代码 复制代码 收藏代码
  1. hibernate.search.default.directory_provider filesystem
  2. hibernate.search.default.indexBase=/usr/lucene/indexes
  3. hibernate.search.Rules.directory_provider ram
  4. hibernate.search.Actions.directory_provider com.acme.hibernate.CustomDirectoryProvider
hibernate.search.default.directory_provider filesystem
hibernate.search.default.indexBase=/usr/lucene/indexes
hibernate.search.Rules.directory_provider ram
hibernate.search.Actions.directory_provider com.acme.hibernate.CustomDirectoryProvider

Tip:通过这种配置规则,可以很容易的为每个不同的index配置属性。

 

Table 3.1. List of built-in DirectoryProviders

Class or shortcut name Description Properties
ram Directory基于缓存,该Directory只能应用于唯一的index名称。也就是说该Directory不能在同一应用中使用两次 none
filesystem 基于文件系统的Directory,index所在地址为<indexBase>/< indexName >

indexBase:index所在目录

indexName:覆盖@Indexed.index属性

locking_strategy:可选(看3.11)

filesystem_access_type:可以精确地指定DirectoryProvider所使用的FSDirectory的实现类。可选值为:auto,simple(SimpleFSDirectory),nio(NIOFSDirectory),mmap(MMapDirectory)

filesystem-master

类似于filesystem,但它还定期地复制index到source directory。

 

refresh的推荐值为150%的复制index的时间。

 

复制操作是在原来index副本的基础上复制的,因此可以减少复制的时间。

 

DirectoryProvider一般用在JMS后端的master节点

indexBase:同filesystem

indexName:同filesystem

sourceBase:Source (copy) base directory

source:source directory的尾缀,默认是@Indexed.index,实际的source directory为<sourceBase>/<source>

refresh:定义副本隔多长时间复制一次,默认为3600s

buffer_size_on_copy:用于复制副本所用的缓存。默认为16MB

locking_strategy:同filesystem

filesystem_access_type:同filesystem

filesystem-slave

类似于filesystem,但定期地复制master端的source,为了避免锁和不一致性,在本地保留2份copy。

 

retry_marker_lookup:定义在失败前访问source directory中的marker file的次数,每次访问间隔是5秒。default是0。

retry_initialize_period:设置间隔去重试初始化index。

其他属性与filesystem-master一样

infinispan

基于infinispan的directory。保存index在一个分布式的网格,使得集群中的所有机器可以很快的看到index的改变。

Section 3.8, “Infinispan Directory configuration” 有一些额外的要求和配置。

locking_cachename: name of the Infinispan cache to use to store locks.

data_cachename : name of the Infinispan cache to use to store the largest data chunks; this area will contain the largest objects, use replication if you have enough memory or switch to distribution.

metadata_cachename: name of the Infinispan cache to use to store the metadata relating to the index; this data is rather small and read very often,it's recommended to have this cache setup using replication.

chunk_size: large files of the index are split in smaller chunks, you might want to set the highest value efficiently handled by your network.Networking tuning might be useful.

 

 

 

 

3.3分割索引(Sharding Indexes)

当遇到下面两种情形的时候,你可能需要分割索引

  • 当索引文件比较巨大,而导致在索引文件更新的时候使应用变慢。
  • 当只需要搜索索引文件的一个子集的时候,比如索引文件按用户,地区等来划分成不同的片段。

Warning:一般情况下,不推荐使用分割索引,因为在搜索时,应用需要为每个片段打开一个Search。

 

默认情况下,分割索引是不可用的,除非配置了属性 hibernate.search.<indexName>.sharding_strategy.nbr_of_shards 。如Example 3.3, “Enabling index sharding”所示:

 

Example 3.3. Enabling index sharding

Properties代码 复制代码 收藏代码
  1. hibernate.search.<indexName>.sharding_strategy.nbr_of_shards=5
hibernate.search.<indexName>.sharding_strategy.nbr_of_shards=5

负责分割索引的接口是IndexShardingStrategy。默认的sharding strategy是根据id字符串的哈希值(由FieldBridge生成)来分割的。你也可以实现自己的IndexShardingStrategy来覆盖默认的sharding strategy。如Example 3.4. Specifying a custom sharding strategy所示配置自定义IndexShardingStrategy。

Properties代码 复制代码 收藏代码
  1. hibernate.search.<indexName>.sharding_strategy=my.shardingstrategy.Implementation
hibernate.search.<indexName>.sharding_strategy=my.shardingstrategy.Implementation

IndexShardingStrategy可以通过过滤索引片段来优化搜索。通过激活一个过滤器 (see Section 5.3.1, “Using filters in a sharded environment”),sharding strategy可以选择一个索引片段子集来完成搜索从而加快搜索速度。

 

因此,每个索引片段都可以有一个独立的directory provider的配置。假设有一个index名称是Animal,那么分割该index成5个片段后,每个片段的名字就为Animal.0 to Animal.4。如下例Example 3.5, “Sharding configuration for entity Animal”

 

Example 3.5. Sharding configuration for entity Animal

Properties代码 复制代码 收藏代码
  1. hibernate.search.default.indexBase=/usr/lucene/indexes
  2. hibernate.search.Animal.sharding_strategy.nbr_of_shards=5
  3. hibernate.search.Animal.directory_provider=filesystem
  4. hibernate.search.Animal.0.indexName=Animal00
  5. hibernate.search.Animal.3.indexBase=/usr/lucene/sharded
  6. hibernate.search.Animal.3.indexName=Animal03
hibernate.search.default.indexBase=/usr/lucene/indexes
hibernate.search.Animal.sharding_strategy.nbr_of_shards=5
hibernate.search.Animal.directory_provider=filesystem
hibernate.search.Animal.0.indexName=Animal00
hibernate.search.Animal.3.indexBase=/usr/lucene/sharded
hibernate.search.Animal.3.indexName=Animal03

 

在Example 3.5中,配置使用默认的id字符串哈希值分割策略把Animal索引分割成5个索引片段,所有的片段的DirectoryProvider都是filesystem。每个片段保存在如下所示的路径下:

  • 片段0:/usr/lucene/indexes/Animal00(默认的indexBase,覆盖默认的indexName)
  • 片段1: /usr/lucene/indexes/Animal.1(默认的indexBase,默认的indexName)
  • 片段2: /usr/lucene/indexes/Animal.2(默认的indexBase,默认的indexName)
  • 片段3:/usr/lucene/shared/Animal03(覆盖默认的indexBase,默认的indexName)
  • 片段4: /usr/lucene/indexes/Animal.4(默认的indexBase,默认的indexName)

 

3.4共享索引(Sharing indexes)

Sharing indexes可以把不同的实体索引合并到一个单独的Lucene Index文件中。有两种方式达到这个目的:

  • 配置DirectoryProvider指向相同的物理目录,然后配置实体索引的indexName为索引文件的名称。如
    Properties代码 复制代码 收藏代码
    1. hibernate.search.org.hibernate.search.test.shards.Furniture.indexName = Animal
    2. hibernate.search.org.hibernate.search.test.shards.Animal.indexName = Animal
    hibernate.search.org.hibernate.search.test.shards.Furniture.indexName = Animal
    hibernate.search.org.hibernate.search.test.shards.Animal.indexName = Animal
  • 设置@Indexed的index属性为索引文件的名称。如希望Furniture和Animal实体都合并到名字为Animal的索引文件中,那么只需要在Furniture和Animal的类级别上添加注解@Indexed(index="Animal")

Note:Sharing indexes并没有太多的好处,只是一种可选的方式来管理索引文件。

 

 

3.5工作者配置(Worker configuration)

通过Worker configuration可以调整Hibernate Search与Lucene的交互。这里有有个Worker接口,Worker接口的实现负责获取所有实体的改变,把这些改变排成队列,并在上下文结束的时候应用这些改变。大多数的上下文范围,特别是ORM的连接方式,都是事务的。基于这个原因,Hibernate Search默认使用 TransactionalWorker去限定改变的范围为每一个事务处理。但也可能有这样的情景,上下文依赖于实体改变的数量或其他一些应用的生命周期事件。Worker的实现可以参考Table 3.2, “Scope configuration”.来配置。

 

Table 3.2. Scope configuration

Property Description
hibernate.search.worker.scope Worker实现类的全限定名。默认TransactionalWorker
hibernate.search.worker.* Worker实现类的属性配置。*为具体的属性名。
hibernate.search.worker.batch_size 定义每个上下文indexing操作数的最大值。不管上下文是否结束,只要操作数大于这个值,将会触发indexing work。这个属性只有在Worker的实现类委托queue work给BatchedQueueingProcessor(TransactionalWorker就是这样的一个Worker)

 

 

 

当上下文结束,就会把实体类的改变应用到index中去。这个过程可以是同步的,也可以是通过新线程来异步处理。同步更新方式的好处是可以保证index与数据库在任何时刻保持一致,但响应时间相对异步更新方式较长。异步更新方式的优点是响应时间非常的短,但并不能保证数据库与index的一致性。Table 3.3,“Execution configuration”展示了有关运行方式的配置选项。

 

Table 3.3. Execution configuration

Property Description
hibernate.search.worker.execution

sync:同步运行方式(默认)

async:异步运行方式

hibernate.search.worker.thread_pool.size 定义在异步运行方式下,线程池中的线程数量
hibernate.search.worker.buffer_queue.max 只在异步运行方式下有效。定义work queue的最大值。默认是infinite。如果达到上限,work会由主线程完成

 

 

 

到目前为止,不管使用哪种运行方式,所有的work都是由相同的,单独的Virtual Machine (VM)完成。幸运的是有一种更好的方法——委托。这个方法通过配置hibernate.search.worker.backend属性,把indexing work委托给另一个server完成。 see Table 3.4, “Backend configuration”.

 

Table 3.4. Backend configuration

Property Description
hibernate.search.worker.backend

lucene:默认的backend。运行indexing work在同一个VM。

 

jms:JMS backend。index update的操作命令发送给JMS queue,indexing master根据JMS queue的命令更新index。See Table 3.5, “JMS backend configuration” for additional configuration options and Section 3.6, “JMS Master/Slave configuration” for a more detailed descripton of this setup.

 

jgroupsMaster or jgroupsSlave:backend使用JGroups[http://www.jgroups.org/]作为通信层。See Table 3.6, “JGroups backend configuration” for additional configuration options and Section 3.7,“JGroups Master/Slave configuration” for a more detailed description of this setup

 

blackhole:主要用在测试/开发阶段,可以忽略所有indexing work。

 

也可以指定一个实现了BackendQueueProcessorFactory的类(全限定名)。通过这种方式实现了自己的通信层。这个实现的责任是返回一个能完成indexing work的Runnable实例。

 

 

Table 3.5. JMS backend configuration

Property Description
hibernate.search.worker.jndi.* 定义JNDI属性来初始化InitialContext(如果有必要的话)。JNDI只在JMS有用。
hibernate.search.worker.jms.connection_factory required。定义JNDI名称查找JMS connection factory。默认“/ConnectionFactory”如JBoss AS所说一样。
hibernate.search.worker.jms.queue required。定义JNDI名称查找JMS queue。该queue用于发送work messages。

 

 

Table 3.6. JGroups backend configuration

Property Description
hibernate.search.worker.jgroups.clusterName Optional for JGroups back end. Defines the
name of JGroups channel.
hibernate.search.worker.jgroups.configurationFile Optional JGroups network stack configuration.
Defines the name of a JGroups configuration
file, which must exist on classpath
hibernate.search.worker.jgroups.configurationXml Optional JGroups network stack configuration.
Defines a String representing JGroups
configuration as XML.
hibernate.search.worker.jgroups.configurationString Optional JGroups network stack configuration.
Provides JGroups configuration in plain text.

 

Warning:你可以看到,上面配置的属性有些相互间是有关联的,因此有些属性的组合是毫无意义的。这就要求你去掉那些无用的属性配置。另外,在写自定义的BackendQueueProcessorFactory之前,务必先学习已有实现类的源码。

 

3.6. JMS Master/Slave configuration

这一节会更详细地介绍怎么样去配置主/从结构的Hibernate Search architecture。

JMS back end configuration.

 

3.6.1.从节点的配置(Slave nodes)

每次index更新操作都会发送给JMS queue。搜索操作是基于本地的index copy。

 

Example 3.6. JMS Slave configuration

Properties代码 复制代码 收藏代码
  1. ### slave configuration
  2. ## DirectoryProvider
  3. # (remote) master location
  4. hibernate.search.default.sourceBase = /mnt/mastervolume/lucenedirs/mastercopy
  5. # local copy location
  6. hibernate.search.default.indexBase = /Users/prod/lucenedirs
  7. # refresh every half hour
  8. hibernate.search.default.refresh = 1800
  9. # appropriate directory provider
  10. hibernate.search.default.directory_provider = filesystem-slave
  11. ## Backend configuration
  12. hibernate.search.worker.backend = jms
  13. hibernate.search.worker.jms.connection_factory = /ConnectionFactory
  14. hibernate.search.worker.jms.queue = queue/hibernatesearch
  15. #optional jndi configuration (check your JMS provider for more information)
  16. ## Optional asynchronous execution strategy
  17. # hibernate.search.worker.execution = async
  18. # hibernate.search.worker.thread_pool.size = 2
  19. # hibernate.search.worker.buffer_queue.max = 50
### slave configuration

## DirectoryProvider
# (remote) master location
hibernate.search.default.sourceBase = /mnt/mastervolume/lucenedirs/mastercopy

# local copy location
hibernate.search.default.indexBase = /Users/prod/lucenedirs

# refresh every half hour
hibernate.search.default.refresh = 1800

# appropriate directory provider
hibernate.search.default.directory_provider = filesystem-slave

## Backend configuration
hibernate.search.worker.backend = jms
hibernate.search.worker.jms.connection_factory = /ConnectionFactory
hibernate.search.worker.jms.queue = queue/hibernatesearch
#optional jndi configuration (check your JMS provider for more information)

## Optional asynchronous execution strategy
# hibernate.search.worker.execution = async
# hibernate.search.worker.thread_pool.size = 2
# hibernate.search.worker.buffer_queue.max = 50

 

Tip:推荐在从节点本地保存一份index copy来提高Search性能。

 

Tip:刷新间隔应该长于复制的时间。

 

3.6.2. 主节点配置(Master node)

主节点从JMS queue获取index update操作命令并更新index。主节点的index会定期地被复制一个副本。

 

Example 3.7. JMS Master configuration

Properties代码 复制代码 收藏代码
  1. ### master configuration
  2. ## DirectoryProvider
  3. # (remote) master location where information is copied to
  4. hibernate.search.default.sourceBase = /mnt/mastervolume/lucenedirs/mastercopy
  5. # local master location
  6. hibernate.search.default.indexBase = /Users/prod/lucenedirs
  7. # refresh every half hour
  8. hibernate.search.default.refresh = 1800
  9. # appropriate directory provider
  10. hibernate.search.default.directory_provider = filesystem-master
  11. ## Backend configuration
  12. #Backend is the default lucene one
### master configuration

## DirectoryProvider
# (remote) master location where information is copied to
hibernate.search.default.sourceBase = /mnt/mastervolume/lucenedirs/mastercopy

# local master location
hibernate.search.default.indexBase = /Users/prod/lucenedirs

# refresh every half hour
hibernate.search.default.refresh = 1800

# appropriate directory provider
hibernate.search.default.directory_provider = filesystem-master

## Backend configuration
#Backend is the default lucene one

除了Hibernate Search framework的配置之外,还需要写一个Message Driven Bean,并由他来处理来自JMS的indexing work queue。

 

Example 3.8. Message Driven Bean processing the indexing queue

 

Java代码 复制代码 收藏代码
  1. @MessageDriven(activationConfig = {
  2. @ActivationConfigProperty(propertyName="destinationType",
  3. propertyValue="javax.jms.Queue"),
  4. @ActivationConfigProperty(propertyName="destination",
  5. propertyValue="queue/hibernatesearch"),
  6. @ActivationConfigProperty(propertyName="DLQMaxResent", propertyValue="1")
  7. } )
  8. public class MDBSearchController extends AbstractJMSHibernateSearchController
  9. implements MessageListener {
  10. @PersistenceContext EntityManager em;
  11. //method retrieving the appropriate session
  12. protected Session getSession() {
  13. return (Session) em.getDelegate();
  14. }
  15. //potentially close the session opened in #getSession(), not needed here
  16. protected void cleanSessionIfNeeded(Session session)
  17. }
  18. }
@MessageDriven(activationConfig = {
      @ActivationConfigProperty(propertyName="destinationType", 
                                propertyValue="javax.jms.Queue"),
      @ActivationConfigProperty(propertyName="destination", 
                                propertyValue="queue/hibernatesearch"),
      @ActivationConfigProperty(propertyName="DLQMaxResent", propertyValue="1")
   } )
public class MDBSearchController extends AbstractJMSHibernateSearchController 
                                 implements MessageListener {
    @PersistenceContext EntityManager em;
    
    //method retrieving the appropriate session
    protected Session getSession() {
        return (Session) em.getDelegate();
    }

    //potentially close the session opened in #getSession(), not needed here
    protected void cleanSessionIfNeeded(Session session) 
    }
}

 

这个的例子的MDBSearchController继承了Hibernate Search的 AbstractJMSHibernateSearchController(一个抽象的JMS控制类,该类还实现了JavaEE 5 MDB)。该实现只是一个样例,它还可以调整成不需要用到JavaEE MDB(更多信息请看AbstractJMSHibernateSearchController的javadoc关于getSession() 和cleanSessionIfNeeded()方法的说明)

 

3.7.JGroups的主/从 结构的配置(JGroups Master/Slave configuration)

本节将介绍怎样去配置JGroups的 主/从 结构backend。本节的配置与3.6节 “JMS Master/Slave configuration”的配置是一样的,唯一的不同是hibernate.search.worker.backend属性的配置

 

3.7.1.从节点配置(Slave nodes)

每一次的index update操作会经由JGroups channel发送给主节点。搜索操作是基于本地的index copy上进行的。

 

Example 3.9. JGroups Slave configuration

Properties代码 复制代码 收藏代码
  1. ### slave configuration
  2. hibernate.search.worker.backend = jgroupsSlave
### slave configuration
hibernate.search.worker.backend = jgroupsSlave 

3.7.2. 主节点配置(Master node)

主节点从JGroups channel获取index update操作命令并更新index。主节点的index会定期复制一份副本。

 

Example 3.10. JGroups Master configuration

Properties代码 复制代码 收藏代码
  1. ### master configuration
  2. hibernate.search.worker.backend = jgroupsMaster
### master configuration
hibernate.search.worker.backend = jgroupsMaster

 

3.7.3. JGroups channel的配置(JGroups channel configuration)

JGroups传输协议配置是可选的,并且channel name可以被定义和应用到主/从节点。有三种方式定义JGroups传输协议:

  • 设置hibernate.search.worker.backend.jgroups.configurationFile属性并指定一个文件包含有JGroups传输协议配置。
  • 通过hibernate.search.worker.backend.jgroups.configurationXml属性直接嵌入JGroups传输协议的xml配置到Hibernate configuration file
  • 通过hibernate.search.worker.backend.jgroups.configurationString属性直接嵌入JGroups传输协议的字符串配置到Hibernate configuration file

Tip:如果没有任何的JGroups传输协议配置被指定,默认使用 flush-udp.xml配置文件。

 

Example 3.11. JGroups transport protocol configuration

Properties代码 复制代码 收藏代码
  1. ## JGroups configuration options
  2. # OPTION 1 - udp.xml file needs to be located in the classpath
  3. hibernate.search.worker.backend.jgroups.configurationFile = udp.xml
  4. # OPTION 2 - protocol stack configuration provided in XML format
  5. hibernate.search.worker.backend.jgroups.configurationXml =
  6. <config xmlns="urn:org:jgroups"
  7. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  8. xsi:schemaLocation="urn:org:jgroups file:schema/JGroups-2.8.xsd">
  9. <UDP
  10. mcast_addr="${jgroups.udp.mcast_addr:228.10.10.10}"
  11. mcast_port="${jgroups.udp.mcast_port:45588}"
  12. tos="8"
  13. thread_naming_pattern="pl"
  14. thread_pool.enabled="true"
  15. thread_pool.min_threads="2"
  16. thread_pool.max_threads="8"
  17. thread_pool.keep_alive_time="5000"
  18. thread_pool.queue_enabled="false"
  19. thread_pool.queue_max_size="100"
  20. thread_pool.rejection_policy="Run"/>
  21. <PING timeout="1000" num_initial_members="3"/>
  22. <MERGE2 max_interval="30000" min_interval="10000"/>
  23. <FD_SOCK/>
  24. <FD timeout="3000" max_tries="3"/>
  25. <VERIFY_SUSPECT timeout="1500"/>
  26. <pbcast.STREAMING_STATE_TRANSFER/>
  27. <pbcast.FLUSH timeout="0"/>
  28. </config>
  29. # OPTION 3 - protocol stack configuration provided in "old style" jgroups format
  30. hibernate.search.worker.backend.jgroups.configurationString =
  31. UDP(mcast_addr=228.1.2.3;mcast_port=45566;ip_ttl=32):PING(timeout=3000;
  32. num_initial_members=6):FD(timeout=5000):VERIFY_SUSPECT(timeout=1500):
  33. pbcast.NAKACK(gc_lag=10;retransmit_timeout=3000):UNICAST(timeout=5000):
  34. FRAG:pbcast.GMS(join_timeout=3000;shun=false;print_local_addr=true)
## JGroups configuration options
# OPTION 1 - udp.xml file needs to be located in the classpath
hibernate.search.worker.backend.jgroups.configurationFile = udp.xml

# OPTION 2 - protocol stack configuration provided in XML format
hibernate.search.worker.backend.jgroups.configurationXml =
<config xmlns="urn:org:jgroups"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:org:jgroups file:schema/JGroups-2.8.xsd">
<UDP
mcast_addr="${jgroups.udp.mcast_addr:228.10.10.10}"
mcast_port="${jgroups.udp.mcast_port:45588}"
tos="8"
thread_naming_pattern="pl"
thread_pool.enabled="true"
thread_pool.min_threads="2"
thread_pool.max_threads="8"
thread_pool.keep_alive_time="5000"
thread_pool.queue_enabled="false"
thread_pool.queue_max_size="100"
thread_pool.rejection_policy="Run"/>
<PING timeout="1000" num_initial_members="3"/>
<MERGE2 max_interval="30000" min_interval="10000"/>
<FD_SOCK/>
<FD timeout="3000" max_tries="3"/>
<VERIFY_SUSPECT timeout="1500"/>
<pbcast.STREAMING_STATE_TRANSFER/>
<pbcast.FLUSH timeout="0"/>
</config>

# OPTION 3 - protocol stack configuration provided in "old style" jgroups format
hibernate.search.worker.backend.jgroups.configurationString =

UDP(mcast_addr=228.1.2.3;mcast_port=45566;ip_ttl=32):PING(timeout=3000;
num_initial_members=6):FD(timeout=5000):VERIFY_SUSPECT(timeout=1500):
pbcast.NAKACK(gc_lag=10;retransmit_timeout=3000):UNICAST(timeout=5000):
FRAG:pbcast.GMS(join_timeout=3000;shun=false;print_local_addr=true)

JGroups的主/从节点是通过JGroups channel通信的。默认的channel name是HSearchCluster。也可以像Example 3.12,“JGroups channel name configuration”.一样修改。

 

Example 3.12. JGroups channel name configuration

Properties代码 复制代码 收藏代码
  1. hibernate.search.worker.backend.jgroups.clusterName = Hibernate-Search-Cluster
hibernate.search.worker.backend.jgroups.clusterName = Hibernate-Search-Cluster 

3.8.Infinispan Directory配置(Infinispan Directory configuration)

Infinispan是一个分布式的,规模可变的(scalable),高度可用的数据网格平台,它支持自动检测平等节点。当把Infinispan与Hibernate Search组合起来,这样就可以在分布式环境下保存Lucene index并且各个节点的index更新得很快。

 

本节会更详细地介绍怎样在Hibernate Search上应用Infinispan Directory。

 

使用Infinispan Directory时,index是保存在内存中,并与各个节点共享这个index。可以看作是所有节点所共有的一个单独的Directory。如果一个节点更新了index,其他的节点的index也已经被更新了,所以在一个节点上的所有更新,集群中的其他节点也会搜索到这些更新。

 

默认的配置是把所有的index数据复制到各个节点上,这无疑要消耗大量的内存。对于体积大的index来说,它应该使用数据分布式结构,由集群中的各个成员保存index的一部分数据。

 

也可以释放一部分的数据到CacheStore,像普通的文件系统,Amazon S3, Cassandra, Berkley DB或关系型数据库。你可以在每个节点上配置一个CacheStore,或集中到一个单独的CacheStore由所有的节点共享。

 

要查看更详细的配置信息请查看Infinispan文档[http://www.jboss.org/infinispan/]

 

3.8.1. 要求(Requirements)

Infinispan要求使用java6和最新版的JGroups。要应用Infinispan directory需要在Maven上添加以下依赖。

 

Example 3.13. Maven dependencies for Hibernate Search

Xml代码 复制代码 收藏代码
  1. <dependency>
  2. <groupId>org.hibernate</groupId>
  3. <artifactId>hibernate-search</artifactId>
  4. <version>3.4.0.Final</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.hibernate</groupId>
  8. <artifactId>hibernate-search-infinispan</artifactId>
  9. <version>3.4.0.Final</version>
  10. </dependency>
<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-search</artifactId>
   <version>3.4.0.Final</version>
</dependency>
<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-search-infinispan</artifactId>
   <version>3.4.0.Final</version>
</dependency>

对于非Maven的用户来说,添加hibernate-search-infinispan.jar, infinispan-lucene-directory.jar和infinispan-core.jar到应用的classpath。后面两个jar文件是由Infinispan[http://sourceforge.net/projects/infinispan/files/]发布的。同样也需要updated JGroups版本满足Infinispan的需要。

 

3.8.2. Architecture

即使使用了Infinispan directory,但还是推荐使用JMS Master/Slave或JGroups backend,因为所有的节点会使用同一个index,这样的话每个节点的IndexWriter都会尝试去获取同一个index的锁。因此通过发送更新操作给JMS queue或JGroups channel,代替直接应用更新到index,从而可以用其中一个从节点代表所有的节点来更新index。

 

并不是强制要求配置一个非默认的backend,但可以改善应用的性能,因为只有一个节点需要进行写操作。

 

配置JMS从节点只需要修改backend并把DirectoryProvider设为infinispan。在主节点也应设为infinispan,这样主/从节点间就不再需要安排复制的工作也能连接起来。使用JGroups backend也是一样,把DirectoryProvider配置为infinispan和backend的配置组织起来就可以了。

 

 

3.8.3. Infinispan Configuration

该配置很简单,只需要激活backend:

Properties代码 复制代码 收藏代码
  1. hibernate.search.default.directory_provider=infinispan
hibernate.search.default.directory_provider=infinispan

配置了上面的属性就可以得到了一个集群复制(cluster-replicated)的index,但默认的配置并不到保证index的持久性。要解决这个问题还需要一个infinispan的配置文件。

 

要使用infinispan,Hibernate Search需要一个CacheManager,它可以通过JNDI查找和重用一个已经存在的CacheManager,或新建和管理一个新的CacheManager。在后一种情况,CacheManager由Hibernate Search管理它的开始和结束(当SessionFactory关闭的时候关闭)

 

通过JNDI使用已存在的 CacheManager(可选的):

Properties代码 复制代码 收藏代码
  1. hibernate.search.infinispan.cachemanager_jndiname = [jndiname]
hibernate.search.infinispan.cachemanager_jndiname = [jndiname]

通过一个配置文件开启一个新的CacheManager(可选的):

Properties代码 复制代码 收藏代码
  1. hibernate.search.infinispan.configuration_resourcename = [infinispan configuration filename]
hibernate.search.infinispan.configuration_resourcename = [infinispan configuration filename]

如果两个属性都有配置的话,会优先使用JNDI的配置。如果两个属性都没有配置,Hibernate Search会使用保存在hibernate-search-infinispan.jar中的默认的Infinispan配置。默认配置能满足大部分的需要,但不能保存index在持久的cache store。

 

如Table 3.1, “List of built-in DirectoryProviders”提到的,每个index有三种不同的存储区,需要为hibernate-search-infinispan.jar中的hibernatesearch-infinispan.xml配置这三种不同的存储区。多个不同的index可以共用同一个存储区。

 

Warning:在Infinispan中使用JGroups,要求JVM属性java.net.preferIPv4Stack设置为true。即-Djava.net.preferIPv4Stack=true

 

3.9. Reader strategy配置(Reader strategy configuration)

在2.3节中已经介绍过两种不同的reader strategy:

  • shared:多次查询共用相同的IndexReader。这种策略是高效的。
  • not-shared:每次查询都会打开一个新的IndexReader。

默认的reader strategy是shared。它也可以通过下面的属性修改:

Properties代码 复制代码 收藏代码
  1. hibernate.search.reader.strategy = not-shared
hibernate.search.reader.strategy = not-shared

 

或使用一个自定义的reader strategy:

Properties代码 复制代码 收藏代码
  1. #my.corp.myapp.CustomReaderProvider是一个自定义的reader strategy实现。
  2. hibernate.search.reader.strategy = my.corp.myapp.CustomReaderProvider
#my.corp.myapp.CustomReaderProvider是一个自定义的reader strategy实现。
hibernate.search.reader.strategy = my.corp.myapp.CustomReaderProvider

 

3.10. 调整Lucene的indexing性能(Tuning Lucene indexing performance)

Hibernate Search可以通过指定一系列的参数来调整Lucene的indexing性能,实际上,是把这些参数赋值到底层的Lucene IndexWriter,比如参数 mergeFactor,maxMergeDocs和maxBufferedDocs。你可以配置所有index的默认参数,或具体index的参数,甚至是具体的index shard。

 

根据实际情况而定,有两个集合的参数用于不同的性能设置:

  • 如果indexing操作是由数据库的修改来触发的,参数由关键字transaction分组。如
    Properties代码 复制代码 收藏代码
    1. hibernate.search.[default|<indexname>].indexwriter.transaction.<parameter_name>
    hibernate.search.[default|<indexname>].indexwriter.transaction.<parameter_name>
  • 如果indexing操作发生在FullTextSession.index()或MassIndexer(see Section 6.3,“Rebuilding the whole index”),参数由关键字batch分组
    Properties代码 复制代码 收藏代码
    1. hibernate.search.[default|<indexname>].indexwriter.batch.<parameter_name>
    hibernate.search.[default|<indexname>].indexwriter.batch.<parameter_name>

如果没有index shard的配置,Hibernate Search就会应用index的配置,如果也没有对应的index配置,便应用default配置。

 

Example 3.14. Example performance option configuration

Properties代码 复制代码 收藏代码
  1. hibernate.search.Animals.2.indexwriter.transaction.max_merge_docs=10
  2. hibernate.search.Animals.2.indexwriter.transaction.merge_factor=20
  3. hibernate.search.default.indexwriter.batch.max_merge_docs=100
hibernate.search.Animals.2.indexwriter.transaction.max_merge_docs=10
hibernate.search.Animals.2.indexwriter.transaction.merge_factor=20
hibernate.search.default.indexwriter.batch.max_merge_docs=100

上面的例子中,Animal的第二个index shard的实际配置如下:

  • transaction.max_merge_docs = 10
  • batch.max_merge_docs = 100
  • transaction.merge_factor = 20
  • 其它使用Lucene里设定的默认值

Table 3.7,“List of indexing performance and behavior properties”展示了各种调整参数,但这些参数依赖于lucene版本。表中所示的参数对应Lucene2.4

Property Description Default Value
hibernate.search.[default|<indexname>].exclusive_index_use 如果此index没有其他线程的并发写操作,应设为true,这样Hibernate Search对该index运行在exclusive mode模式,从而改善indexing update的性能。 false
hibernate.search.[default|<indexname>].max_queue_length 每个index有一个独自的“pipeline”,pipeline包含了要应用到index的所有更新。当该queue到达了最大长度,就变成了阻塞操作。一般配置这个参数没有太大的意义,除非worker.execution配置为async。 1000
hibernate.search.[default|<indexname>].indexwriter.[transaction|batch].max_buffered_delete_terms 决定在刷新缓存中的delete terms所需要的delete terms的最小值。如果同时有documents在缓存中,它们会被整合和创建一个新的segment。 Disabled (flushes by RAM usage)
hibernate.search.[default|<indexname>].indexwriter.[transaction|batch].max_buffered_docs 控制在indexing期间缓存document的数量。值越大,内存消耗越大。 Disabled (flushes by RAM usage)
hibernate.search.[default|<indexname>].indexwriter.[transaction|batch].max_merge_docs 定义一个segment允许包含document的最大值。值越大有利于batched indexing和提高搜索速度。值越小对transaction indexing越有利。 Unlimited
(Integer.MAX_VALUE)
hibernate.search.[default|<indexname>].indexwriter.[transaction|batch].merge_factor 控制segment merge的频率和大小。定义了当发生插入操作,多久一次segment indexes整合。值越小,在indexing时消耗的内在越小,搜索会更快,但indexing的速度会慢些。值越大则相反。值>10有利于batch index的创建,值<10是交互式维护(interactively maintained)。该值必须大于2。 10
hibernate.search.[default|<indexname>].indexwriter.[transaction|batch].ram_buffer_size 定义用于缓存document的内存的使用量。如果也同时配置了max_buffered_docs,会优先使用max_buffered_docs刷新缓存。一般来说,为了有更好的indexing性能,一般使用ram_buffer_size配置而不是max_buffered_docs,如果可以的话提高ram_buffer_size也能提高一定的性能。 16MB
hibernate.search.[default|<indexname>].indexwriter.[transaction|
batch].term_index_interval
专家:定义term之间的间隔。值越大,可以减少IndexReader的内存消耗,但会降低随机访问term的速度。值越小,则相反。 128
hibernate.search.[default|<indexname>].indexwriter.[transaction|
batch].use_compound_file
使用组合文件格式的好处是减少描述文件。缺点是indexing将花费更长的时间和临时硬盘空间。 true
hibernate.search.enable_dirty_check 并不是所有的实体改变都要更新index。如果所有的修改过的实体属性(脏属性)并没有实际上的改变,Hibernate Search将跳过reindexing work。如果你使用了自定义的FieldBridge,应该禁用该参数,因为FieldBridge是在每次更新时被调用即使FieldBridge没有改变。该参数也不能应用于带@ClassBridge或@DynamicBoost注解的类。 true

 

 

Tip:如果应用结构允许的话,使用hibernate.search.default.exclusive_index_use=true将大幅度地提高index writing。

 

Tip:为了调试indexing速度,将从数据库提取对象与写对象到index相隔离显示非常有用。要达到这个目的,可以设置worker backend为blackhole并运行indexing程序。 blackhole backend并没有禁用Hibernate Search,它会生成必需要的改变集(changesets)到index,但不会刷新缓存到index。相对于设置hibernate.search.indexing_strategy=manual,使用blackhole可能会从数据库中导出更多的数据,因为相关联的实体也会reindexed。推荐的方法是先把焦点放在对象加载优化上(从数据库),然后再调节indexing。

 

Warning:blackhole不应该应用在产品阶段,它只是一个工具去鉴别indexing的瓶颈。

 

3.11. LockFactory配置(LockFactory configuration)

Lucene的Directory有默认的锁策略,这些策略在大多数情况下工作得很好。在Hibernate Search中,你可以为每个index指定LockFactory来管理锁。有些锁策略要求一个filesystem级别的锁,甚至可以用在基于内存的index,但这是不推荐的而且没有什么用途的。

 

通过hibernate.search.<index>.locking_strategy属性可以设置LockFactory,有4个开箱即用的选项:simple, native, single 或 none 。另外还可以设置org.hibernate.search.store.LockFactoryFactory的一个实现类的全限定名。

 

Table 3.8. List of available LockFactory implementations

name Class Description
simple org.apache.lucene.store.SimpleFSLockFactory

基于Java File API的安全实现,它创建一个标志文件来标识一个index已经在使用。

 

如果有需要的话,你可以删除这个锁文件。

 

filesystem, filesystem-master和filesystem-slave这三个DirectoryProvider的默认锁就是simple。

native org.apache.lucene.store.NativeFSLockFactory

像simple锁策略一样, 也是通过创建一个标志文件来标识一个index已经在使用。但该文件是使用本地OS文件,所有即使应用崩溃,锁也能被清除。

该锁在NFS中是有问题的。

single org.apache.lucene.store.SingleInstanceLockFactory

这个LockFactory不会使用一个标志文件,而是一个保存在内存中的Java锁对象,因此,这个LockFactory只用在单线程中。ram DirectoryProvider默认使用这个锁策略

none org.apache.lucene.store.NoLockFactory 不应用任何的锁策略。

 

 

配置样例:

Properties代码 复制代码 收藏代码
  1. hibernate.search.default.locking_strategy=simple
  2. hibernate.search.Animals.locking_strategy=native
  3. hibernate.search.Books.locking_strategy=org.custom.components.MyLockingFactory
hibernate.search.default.locking_strategy=simple
hibernate.search.Animals.locking_strategy=native
hibernate.search.Books.locking_strategy=org.custom.components.MyLockingFactory

3.12. 异常管理配置(Exception Handling Configuration)

Hibernate Search允许配置怎么处理indexing过程中出现的异常。如果不提供任何的异常配置,异常会通过log记录并打印出来。也可以通过下面方式明确的声明logging机制:

Java代码 复制代码 收藏代码
  1. hibernate.search.error_handler=log
hibernate.search.error_handler=log

 

默认的异常处理可以同时作用于同步或异步运行方式。Hibernate Search提供了一个简单的机制来重写默认的异常处理器。自定义异常处理器必须实现ErrorHandler接口,该接口要求实现handle(ErrorContext context)方法。ErrorContext提供了一个LuceneWork实例的引用,底层的异常和并发的LuceneWork实例是不可以被处理的。

 

Java代码 复制代码 收藏代码
  1. public interface ErrorContext {
  2. List<LuceneWork> getFailingOperations();
  3. LuceneWork getOperationAtFault();
  4. Throwable getThrowable();
  5. boolean hasErrors();
  6. }
public interface ErrorContext  {
   List<LuceneWork> getFailingOperations();
   LuceneWork getOperationAtFault();
   Throwable getThrowable();
   boolean hasErrors();
}

 

在Hibernate Search中注册异常处理器(全限定名):

Properties代码 复制代码 收藏代码
  1. hibernate.search.error_handler=CustomerErrorHandler  
hibernate.search.error_handler=CustomerErrorHandler
posted @ 2013-04-30 15:23  眉间尺之魂  阅读(661)  评论(0编辑  收藏  举报