1 Configuring solrconfig.xml
solrconfig.xml文件中包含了Solr需要的大部分参数,当你配置Solr时,你会经常性地使用solrconfig.xml。你可能会配置下述的一些重要特征,包括:
- request handlers(请求控制器);
- listeners(监听器,监听与具体的查询请求相关的时间;
- 监听器可以用来触发执行特定代码,比如使用共同的查询使缓存升温),请求调度管理Http通信;
- Admin网络管理接口;
- 与复制、备份相关的参数(这些参数的具体信息在Legacy Scaling and Distribution中)。
solrconfig.xml文件可以在solr/conf/目录下找到。作为示例的文件包括了良好的注释信息,也包括了适用于大多数情况的配置信息。
这一章节包含了下列主题:
- DataDir and DirectoryFactory in SolrConfig
- Lib Directives in SolrConfig
- Managed Schema Definition in SolrConfig
- IndexConfig in SolrConfig
- UpdateHandlers in SolrConfig
- Query Settings in SolrConfig
- RequestDispatcher in SolrConfig
- RequestHandlers and SearchComponents in SolrConfig
Substituting Properties in Solr Config Files
Solr支持在配置文件中替换属性变量的值,即它允许在solrconfig.xml中定制各种运行时配置。这里的语法是:${propertyname[:option default value]}。它允许定义默认的值并在Solr载入时使用(原文用的是overridden)。如果一个属性的默认值没有设定,那么这个属性必须在运行时设定,否则配置文件将会在被分析的时候产生错误。
这里提供了多种方法在配置文件中设置属性。
JVM System Properties
任何JVM系统属性,通常在启动时使用-D标志指定,可以在Solr中作为任意XML配置文件的变量使用。
例如,在作为示例的solrconfig.xml中,你可以看到被定义为锁类型的值的使用。
1
|
<lockType>${solr.lock.type:native}</lockType>
|
这表示锁类型被默认为“native”,但是当启动Solr的示例应用时,你可以通过启动JVM来覆写这个值:
1
|
java -Dsolr.lock.type=simple -jar start.jar
|
solrcore.properties
如果配置设定的Solr core的路径下包含一个名为solrcore.properties的文件,那么这个文件可以包含任意由用户定义的、符合Java标准属性格式的属性名和属性值。这些属性(和值)可以作为配置Solr core的XML文件的变量使用。
例如,可以在Solr实例的配置文件路径solr/collection1/conf下创建下面的solrcore.properties文件,用来设置lockType的使用:
1
2
|
#conf/solrcore.properties
lock.
type
=
simple
|
注意!solrcore.properties文件的路径和名称可以在属性文件(?)core.properties中被重写。
User defined properties from core.properties
如果使用新的solr.xml的发现模式(?),即每个Solr core拥有一个core.properties文件,那么任何用户都可以在文件中定义特定的属性,并且这些属性在分析Solr core的XML配置文件被替换。
例如,考虑下面的core.properties文件:
1
2
3
|
#core.properties
name
=
collection2
my.custom.prop
=
edismax
|
其中,my.custom.prop属性可以作为变量使用:
1
2
3
4
5
|
<
requestHandler
name
=
"/select"
>
<
lst
name
=
"defaults"
>
<
str
name
=
"defType"
>${my.custom.prop}</
str
>
</
lst
>
</
requestHandler
>
|
User defined properties from the Legacy solr.xml Format
类似于上面的core.properties选项,用户定义的属性应该在传统格式的solr.xml中指定。请参考“User Defined Properties in solr.xml”部分中关于传统的solr.xml配置文档以获得更多细节。
Implicit Core Properties
一些在Solr core中“隐式”的属性有多个替代值,独立于它们何时或也何种方法初始化。举个例子:不考虑一个特定的Solr core的名字是否显式地配置在core.properties中或者有示例的目录名推断获得,隐式的属性solr.core.name可以在core的配置文件中作为一个变量出现……
1
2
3
4
5
|
<requestHandler name="/select">
<lst name="defaults">
<str name="collection_name">${solr.core.name}</str>
</lst>
</requestHandler>
|
所有隐式的属性使用“solr.core.”作为名字的前缀,并且会反射到相同的core.properties属性的运行时的值(?)
solr.core.name
solr.core.config
solr.core.schema
solr.core.dataDir
solr.core.transient
solr.core.loadOnStartup
More Information
- Solr Wiki拥有关于solrconfig.xml的完成的页面,在http://wiki.apache.org/solr/SolrConfigXml.
- 6 Sins of solrconfig.xml modifications from solr.pl
1.1 DataDir and DirectoryFactory in SolrConfig
Solr默认存储它的索引文件在Solr home的/data路径下。如果你想要设定一个不同的路径存储索引文件,那么请使用solrconfig.xml中的参数。你可以设定另一个文件路径。你可以使用完整的路径或者相对于当前servlet容器的工作路径的路径。例如:
1
|
<
dataDir
>/var/data/solr/</
dataDir
>
|
如果你使用了Solr索引文件的备份(在Legacy Scaling and Distribution部分有说明),那么路径应当同配置备份时使用的索引路径相符合。
Specifying the DirectoryFactory For Your Index
默认的solr.StandardDirectoryFactory是基于文件系统的,并且试图选择对当前JVM和平台最好的实现。你可以通过设定solr.MMapDirectoryFactory,solr.NIOFSDirectoryFactory或者solr.SimpleFSDirectoryFactory强行设置一个特定的实现。
1
2
|
<
directoryFactory
name
=
"DirectoryFactory"
class
=
"${solr.directoryFactory:solr.StandardDirectoryFactory}"
/>
|
solr.RAMDirectoryFactory是基于内存的,非持久的,并且和备份无关。通过使用DirectoryFactory在RAM中存储索引文件:
1
|
<
directoryFactory
class
=
"org.apache.solr.core.RAMDirectoryFactory"
/>
|
1.2 Lib Directives in SolrConfig
Solr允许通过在solrconfig.xml中定义指令载入插件。
这些插件按照它们出现在solrconfig.xml中的顺序被载入。如果存在依赖,那么将最低层次的依赖jar放在最前面。
正则表达式可以用于支持载入jar包过程的控制(这依赖于其他在同一路径下的jar包)。所有路径值都是相对于Solr instanceDir的相对路径。
1
2
3
4
5
6
7
8
|
<
lib
dir
=
"../../../contrib/extraction/lib"
regex
=
".*\.jar"
/>
<
lib
dir
=
"../../../dist/"
regex
=
"solr-cell-\d.*\.jar"
/>
<
lib
dir
=
"../../../contrib/clustering/lib/"
regex
=
".*\.jar"
/>
<
lib
dir
=
"../../../dist/"
regex
=
"solr-clustering-\d.*\.jar"
/>
<
lib
dir
=
"../../../contrib/langid/lib/"
regex
=
".*\.jar"
/>
<
lib
dir
=
"../../../dist/"
regex
=
"solr-langid-\d.*\.jar"
/>
<
lib
dir
=
"../../../contrib/velocity/lib"
regex
=
".*\.jar"
/>
<
lib
dir
=
"../../../dist/"
regex
=
"solr-velocity-\d.*\.jar"
/>
|
1.3 Managed Schema Definition in SolrConfig
Schema API使得通过REST接口修改schema成为可能(也支持以只读形式访问所有schema元素)。
允许程序访问一个配置文件,并同时允许手动编辑配置文件,这种规则产生了一些挑战:系统生成和手动编辑可能产生重叠,系统生成的编辑可能会删除注释或者其他帮助理解域、域类型的关键性的自定义内容。你可能希望通过源码控制标记(配置)文件的版本,或者同时限制手动编辑。
Solrconfig.xml允许Solr schema被定义为“被管理的索引模式”:只能通过Schema API修改schema。下面是例子:
1
2
3
4
5
6
7
|
<!--
<schemaFactory class="ManagedIndexSchemaFactory">
<bool name="mutable">true</bool>
<str name="managedSchemaResourceName">managed-schema</str>
</schemaFactory>
-->
<
schemaFactory
class
=
"ClassicIndexSchemaFactory"
/>
|
在上面的例子中, solrconfig.xml实际上被配置为使用ClassicIndexSchemaFactory处理schema.xml文件,即允许手动修改。这个设置不允许使用Schema API修改schema。
你可以在注释部分给出的示例中看到配置managed schema的方法。为了使通过Schema API修改schema成为可能,需要配置使用ManagedIndexSchemaFactory。参数mutable必须被设置为true。managedSchemaResourceName属性的值默认为“managed-schema”,这个值也可以被设定为任何与“schema.xml”不同的值。
每当Solr重新启动的时候,已经存在的schema.xml文件被重命名为schema.xml.bak,同时文件内容会被写入一个名为mana的文件。如果你打开结果文件查看,你会在文件的开头看到下面一行内容:
1
|
<!-- Solr managed schema - automatically generated - DO NOT EDIT -->
|
注意,在example/example-schemaless/下的Schemaless模式的例子使用了ManagedIndexSchemaFactory以允许基于文档更新域的值的schema域的自动添加。
1.4 IndexConfig in SolrConfig
Solrconfig.xml的部分从底层定义了Lucene index writers的行为。
在默认情况下,在作为示例的Solr的solrconfig.xml文件中,这些设置项被注释掉了,这意味这Solr使用了默认的值。在大多数情况下,使用默认值就可以了。
1
2
3
|
<
indexConfig
>
...
</
indexConfig
>
|
注意!在Solr 4之前的版本,上述的这些设置项目的很大部分被包括在mainIndex 和indexD
efaults 中。在Solr 4中,这些部分被废弃并移除。现在,所有设定项都集中在了。
1.4.1 Sizing Index Segments
ramBufferSizeMB
每当积累的更新文档超过了这个值规定的内存空间(用兆字节megabytes定义),这些更新就被写入硬盘。这个动作可能生成新的段或者引发段的合并。使用这个值通常要优于使用maxBufferedDocs。如果在solrconfig.xml中同时设置了maxBufferedDocs和ramBufferSizeMB,那么一次写入硬盘的动作会发生在达到这两个限制中的任何一个的时候。默认的设置是100Mb(在Solr 4.1中是32Mb)。
1
|
<
ramBufferSizeMB
>100</
ramBufferSizeMB
>
|
maxBufferedDocs
用于设定在写入硬盘并加入当前索引段前内存缓冲中的更新文档的数目。如果一个段满了,那么会生成一个新的段,或者进行合并。默认的Solr配置中没有定义这个值。
1
|
<
maxBufferedDocs
>1000</
maxBufferedDocs
>
|
maxIndexingThreads
定义了用于索引文件的并发线程的最大数目。当达到了这个阙值,新加入的线程会等待其他线程结束。默认值是8。这个参数是在Solr 4.1版本加入的。
1
|
<
maxIndexingThreads
>8</
maxIndexingThreads
>
|
UseCompoundFile
设定为true会将一个段的多个文件合并为唯一的文件,默认为false。在那些每个进程允许打开的文件数目被限制的系统中,设置这个值为true可能避免达到限制(如果操作系统是Linux/Unix,那么使用ulimit命令可以更改打开文件数上限。其他操作系统则有类似的方法)。在一些情况下,一些内部因素会设置一个段为“compound=false”,即使这个设定值被显式地置为true,所以一个段的文件的合并并不总是会发生。
更新一个已经合并的索引会由于一些不同的原因导致小的性能损失,这决定于运行时的系统环境。例如,文件系统的缓冲通常和打开文件描述符是相关的,而打开文件描述符可能限制了每个索引能使用的缓存大小。
这个设定同时也会影响在索引备份操作时有多少数据需要转移。这个设定的默认值为false。
1
|
<
useCompoundFile
>false</
useCompoundFile
>
|
1.4.2 Merging Index Segments
mergeFactor
mergeFactor控制了一个Lucene索引在被合并为一个段(segment)前能够存在的段的数量。当索引被更新,它被添加于当前被打开的段中。当段被填满(参见上文中提到的maxBufferedDocs和ramBufferSizeMB参数),一个新的段就会产生,而接下来的更新则会在这里完成。
如果创建一个新段会导致最底层的段的数量超过mergeFactor的值,那么所有这些段就会被合并成一个单独的更大的段。所以如果mergeFactor的值为10,那么合并后生成的唯一的段的大小就大致上等于合并前每个段的十倍。当mergeFactor设置被用于那些较大的段,之后这些段会合并成一个更大的段。这个动作可以被无限制地持续下去。
选择最佳的mergeFactor通常是索引速度和搜索速度的折中。当索引包含更少的段的时候通常可以加速搜索,因为需要加锁的地方更少。这通常也意味着在硬盘上更少的物理文件。但是,保持段的数量保持在低的水平,索引合并过程就会发生更多次,这一动作会加大系统的负担并且减慢更新索引的速度。
相反的,保持更多的段可以加速索引过程,因为合并操作发生的次数较少,在进行更新时更少的触发合并。但是搜索时的代价会变得可观,搜索速度也会下降,因为搜索一个词(term)需要查看索引中的更多的段。更快的索引更新速度意味着更短的提交周转时间,也意味着更长的搜索时间。
在示例的solrconfig.xml中默认的值是10,这是一个合理的开始(即可以在这个基础上调优)。
1
|
<
mergeFactor
>10</
mergeFactor
>
|
mergePolicy
定义了合并过程如何完成。在Solr中的默认值是TieredMergePolicy。这个默认的策略是合并那些差不多大小的段,受制于每次合并时允许的段的数量。其他可用的策略包括LogMergePolicy,LogByteSizeMergePolicy和LogDocMergePolicy。对于这些策略的更多信息,参考MergePolicy javadocs。(Lucene的这部分源码还真没看……)
1
2
3
4
|
<
mergePolicy
class
=
"org.apache.lucene.index.TieredMergePolicy"
>
<
int
name
=
"maxMergeAtOnce"
>10</
int
>
<
int
name
=
"segmentsPerTier"
>10</
int
>
</
mergePolicy
>
|
注意!当使用TieredMergePolicy 时,设置项maxMergeDocs 是不需要的。因为这是Solr的默认设置,所以它被有效地移除了。如果使用别的策略,则这个设置可能依旧是有效的。
mergeScheduler
合并调度程序(merge scheduler)控制了合并的实现。默认值是ConcurrentMergeScheduler,使用单独的线程在后台执行合并。作为替换的选择,SerialMergeScheduler不使用单独的线程进行合并操作。
1
|
<
mergeScheduler
class
=
"org.apache.lucene.index.ConcurrentMergeScheduler"
/>
|
mergedSegmentWarmer
当使用Solr的近实时搜索功能(Near Real Time Searching),可以配置一个合并段的加热器(merged segment warmer)在提交合并前加热在新合并段上的读取器(Reader)。这对于NRT搜索并不是必须的,但可以减少在一次合并结束后打开一个新的NRT读取器时搜索的潜伏时间。
1
|
<
mergedSegmentWarmer
class
=
"org.apache.lucene.index.SimpleMergedSegmentWarmer"
/>
|
1.4.3 Index Locks
lockType
LockFactory的选择决定了它的实现。
lockType=single使用了SingleInstanceLockFactory,目标是一个只读的索引或者其他的进程不可能修改索引的情况。
lockType=native使用NativeFSLockFactory去设置一个操作系统原生的文件锁。不要在多个Solr web应用程序跑在同一个JVM中并试图分享唯一一个索引的情况下使用。
lockType=simple使用SimpleFSLockFactory去设置一个空文件作为锁(大概是这个意思)。
在Solr 3.6和之后的版本中,默认使用native。在其他版本则默认使用simple。
关于LockFactory的细微差别的更多信息,参考http://wiki.apache.org/lucene-java/AvailableLockFactories.
1
|
<
lockType
>native</
lockType
>
|
unlockOnStartup
如果设置为true,那么当系统启动时,任何已经存在的写锁或者提交锁会解锁。这个设置破坏了使多个进程安全地访问Lucene索引文件的锁机制。默认值是false,当改变这个值的时候要小心。当lockType使用none或者single的时候这个参数不被使用。
1
|
<
unlockOnStartup
>false</
unlockOnStartup
>
|
writeLockTimeout
一个IndexWriter等待一个写锁的最长时间。默认值是1000,单位是毫秒。
1
|
<
writeLockTimeout
>1000</
writeLockTimeout
>
|
1.4.4 Other Indexing Settings
还有一些其他的参数对于配置你的实现可能很重要。这些设置影响什么时候并且如何更新索引。
设置 |
描述 |
termIndexInterval |
控制词汇(term)载入内存的时间(often?)。默认值是128。 |
reopenReaders |
设置使得IndexReader可以re-opened,取代先关闭再打开的过程,这个过程通常是较为抵消的。默认值是true。 |
deletionPolicy |
控制在调用回滚时多少提交(commit)会被储存下来。默认是SolrDeletionPolicy,这个参数使用下级参数,包括:保存的提交的最大数目(maxCommitsToKeep),保存的优化的最大数目(maxOptimizedCommitsToKeep),以及任何提交的最大寿命(maxCommitAge),支持DateMathParser语法。 |
infoStream |
指定了用于在索引过程中写详细调试信息(Solr 日志信息)的潜在的Lucene类。 |
1
2
3
4
5
6
7
8
|
<
termIndexInterval
>128</
termIndexInterval
>
<
reopenReaders
>true</
reopenReaders
>
<
deletionPolicy
class
=
"solr.SolrDeletionPolicy"
>
<
str
name
=
"maxCommitsToKeep"
>1</
str
>
<
str
name
=
"maxOptimizedCommitsToKeep"
>0</
str
>
<
str
name
=
"maxCommitAge"
>1DAY</
str
>
</
deletionPolicy
>
<
infoStream
>false</
infoStream
>
|
注意:maxFieldLength参数自Solr 4开始被移除。如果严格的域的长度对你来说是重要的,你可以使用LimitTokenCountFactory获得类似的行为,它可以用于那些你希望做出限制的域。例如下面的例子将会限制域的大小为10000个字符。
1
|
<
filter
class
=
"solr.LimitTokenCountFilterFactory"
maxTokenCount
=
"10000"
/>
|