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:
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
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
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
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。
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
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为索引文件的名称。如
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。
3.6.1.从节点的配置(Slave nodes)
每次index更新操作都会发送给JMS queue。搜索操作是基于本地的index copy。
Example 3.6. JMS Slave configuration
### 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
### 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
@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
### slave configuration hibernate.search.worker.backend = jgroupsSlave
3.7.2. 主节点配置(Master node)
主节点从JGroups channel获取index update操作命令并更新index。主节点的index会定期复制一份副本。
Example 3.10. JGroups Master configuration
### 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
## 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
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
<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:
hibernate.search.default.directory_provider=infinispan
配置了上面的属性就可以得到了一个集群复制(cluster-replicated)的index,但默认的配置并不到保证index的持久性。要解决这个问题还需要一个infinispan的配置文件。
要使用infinispan,Hibernate Search需要一个CacheManager,它可以通过JNDI查找和重用一个已经存在的CacheManager,或新建和管理一个新的CacheManager。在后一种情况,CacheManager由Hibernate Search管理它的开始和结束(当SessionFactory关闭的时候关闭)
通过JNDI使用已存在的 CacheManager(可选的):
hibernate.search.infinispan.cachemanager_jndiname = [jndiname]
通过一个配置文件开启一个新的CacheManager(可选的):
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。它也可以通过下面的属性修改:
hibernate.search.reader.strategy = not-shared
或使用一个自定义的reader strategy:
#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分组。如
hibernate.search.[default|<indexname>].indexwriter.transaction.<parameter_name>
- 如果indexing操作发生在FullTextSession.index()或MassIndexer(see Section 6.3,“Rebuilding the whole index”),参数由关键字batch分组
hibernate.search.[default|<indexname>].indexwriter.batch.<parameter_name>
如果没有index shard的配置,Hibernate Search就会应用index的配置,如果也没有对应的index配置,便应用default配置。
Example 3.14. Example performance option configuration
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 | 不应用任何的锁策略。 |
配置样例:
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机制:
hibernate.search.error_handler=log
默认的异常处理可以同时作用于同步或异步运行方式。Hibernate Search提供了一个简单的机制来重写默认的异常处理器。自定义异常处理器必须实现ErrorHandler接口,该接口要求实现handle(ErrorContext context)方法。ErrorContext提供了一个LuceneWork实例的引用,底层的异常和并发的LuceneWork实例是不可以被处理的。
public interface ErrorContext {
List<LuceneWork> getFailingOperations();
LuceneWork getOperationAtFault();
Throwable getThrowable();
boolean hasErrors();
}
在Hibernate Search中注册异常处理器(全限定名):
hibernate.search.error_handler=CustomerErrorHandler