web.xml配置文件
SolrDispatchFilter一个Filter,过滤所有的PATH
SolrDispatchFilter.init – 加载CoreContainer,开始启动solr应用
谈CoreContainer类 – CoreContainer
a.实例化CoreContainer时会去寻找solr的home目录,寻找的方法有两个:1.到WEB的环境变量里面去找KEY=java:comp/env/solr/home,2.通过System.getProperty去找KEY=solr.solr.home,3.如果都找不到则使用默认的路径solr/
b.到Filter的初始化参数里面找KEY=solrconfig-filename,如果没有则使用solr.xml,作为solr里包含core的配置文件,如果找到这个文件则加载CoreContainer,首先实例化一个SolrResourceLoader,可以参考接口ResourceLoader的定义
InputStream openResource(String resource) – 获取文件的输入流
List
Object newInstance(String cname, String... subpackages) – 获取指定类名和包路径的类的实例化
读取core配置文件solr.xml获取如下属性
solr/ @persistent
solr/ @sharedLib – 如果此项不是NULL则将这个所有core使用的公共JAR包目录,将这个目录放入SolrResourceLoader的类加载目录的路径中
solr/property – 获取solr所有property里包含的KEY-VALUE,PUT到CoreContainer.containerProperties里去
solr/cores/core – 获取solr下的core,迭代solr/cores/core链表加载core
------
solr/cores/core/ @name – core的name
solr/cores/core/ @instanceDir – core的配置文件目录
solr/cores/core/ @config – core的配置文件名称,默认是solrconfig.xml
solr/cores/core/ @schema – core的schema文件名,默认是schema.xml
solr/cores/core/ @properties – core的property文件名,默认是conf/solrcore.properties
solr/cores/core/ @dataDir – core的存放索引文件的目录,默认是data/
solr/cores/core/property – core的KEY-VALUE数据,会把上面的信息都放到这个Properties中
根据以上信息对这个core实例化一个CoreDescriptor,再根据这个CoreDescriptor创建一个SolrCore
1.实例化一个SolrResourceLoader作为这个core的资源加载器,初始类加载地址为CoreContainer的类加载地址,同时读取core的property文件将
读到KEY-VALUE和core.properties合并起来给这个资源加载器以后用
2.用这个ResourceLoader&core.configName实例化一个SolrConfig,在实例化中使用ResourceLoader获取core.configName的文件流,再将这个文
件流DOM化,再根据solrconfig.xml加载SolrConfig
------
config/lib – JAR包路径都加到SolrResourceLoader中
config/indexDefaults config/mainIndex – 实例化两个SolrIndexConfig对象,将这两个Node下的属性SolrIndexConfig bean化,里面包含的属性主要是lucene建索引需要用到的,比如useCompoundFile,maxBufferedDocs,mergePolicyInfo。indexDefaults作为mainIndex的默认选项
config/mainIndex/reopenReaders – reopenReaders : updateHandler每次commit后会跟新solrCore的当前的reader,如果这个值是true则获取当前的reader.reopen,如果是false则Index.open获取索引的reader
config/query/maxBooleanClauses –booleanQueryMaxClauseCount : solrCore用来设置BooleanQuery子条件最多个数
config/query/boolTofilterOptimizer/ @enabled - filtOptEnabled
config/query/boolTofilterOptimizer/ @cacheSize - filtOptCacheSize
config/query/boolTofilterOptimizer/ @threshold –filtOptThreshold
config/query/useFilterForSortedQuery - useFilterForSortedQuery
config/query/queryResultWindowSize - queryResultWindowSize
config/query/queryResultMaxDocsCached - queryResultMaxDocsCached
config/query/enableLazyFieldLoading –enableLazyFieldLoading
------
core的四个cache配置加载,针对cache配置节点需要加载如下信息
1.node的名称,比如filterCache
2. @class – 得到这个cache的类名,solr提供了两种FastLRUCache&LRUCache
3. @regenerator – 得到在预热新的searcher时旧的searcher的cache添加到新的searcher的行为
4.再让ResourceLoader根据 @class去找到cache的class,根据 @regenerator加载其实例
config/query/filterCache - filterCacheConfig
config/query/queryResultCache - queryResultCacheConfig
config/query/documentCache - documentCacheConfig
config/query/fieldValueCache – fieldValueCacheConfig
在加载完这四个cacheConfig后,如果有哪个没有配置regenerator则会为其设置一个默认的,具体逻辑见SolrIndexSearcher
------
config/mainIndex/unlockOnStartup – unlockOnStartup : solrCore用来首次启动是否清空write.lock锁
config/query/useColdSearcher – useColdSearcher : solrCore当前的searcher引用为null的话且有其他线程在加载的话
来自搜索组件的获取searcher的线程会阻塞等其加载好,如果这个值设置为TRUE则其加载好searcher后这些线程就可以立即返回,否则要等到这个新建的searcher经过热身后才会返回
config/dataDir – dataDir : 索引存放目录
config/query/cache – userCacheConfigs
config/HashDocSet/ @loadFactor – hashSetInverseLoadFactor
config/HashDocSet/ @maxSize – hashDocSetMaxSize
config/query/maxWarmingSearchers – maxWarmingSearchers : solrCore用来限制其正在进行warm操作的
IndexSearcher的个数,warm操作即将其前一个IndexSearcher的cache复制给自己
加载插件 – 根据PATH读取DOM里面所有的NODE,对于每个NODE实例化一个PluginInfo,主要是提取如下信息
a.type -> TagName,例如requestHandler
b.name -> @name 插件名称
c.className -> @class 类名
d.initArgs -> 为NamedListInitializedPlugin准备的,当实例化插件时,如果是NamedListInitializedPlugin会将这个
作为init函数的参数传入做初始化操作
e.attributes –> 属性MAP化
config/requestHandler : solrCore用来配置RequestHandler,转发给请求指明的handler去处理
config/queryParser : solrCore用来配置QueryParser
config/queryResponseWriter : solrCore用来配置QueryResponseWriter,如果查询有指定输出格式则到配置的QueryResponseWriter里查,没有则用默认的
config/searchComponent : solrCore用来配置SearchComponent给RequestHandler用的
config/listener : solrCore用来配置相关事件LISTENER
config/directoryFactory : solrCore用来配置DirectoryFactory
config/mainIndex/deletionPolicy : solrCore用来配置IndexDeletionPolicy
config/indexReaderFactory : solrCore用来配置IndexReaderFactory
config/updateRequestProcessorChain : solrCore用来配置UpdateRequest处理责任链
加载UpdateHandlerInfo,使用updateHandler/ @class,updateHandler/autoCommit/maxDocs
updateHandler/autoCommit/maxTime,updateHandler/commitIntervalLowerBound实例化一个UpdateHandlerInfo :
solrCore用来配置这个core的UpdateHandler
------
3.实例化此core的IndexSchema,使用core schema配置文件schema.xml初始化IndexSchema,IndexSchema是一个组织
Document.Field类型的数据结构,里面主要分为两个部分一是对类型的定义,二是Document里面包括哪些Field,需指定这些Field的名称,类型;同时还可以指定默认的Field,设置唯一键,设置BooleanQuery的默认关系AND|OR
a.schema/types/fieldtype | schema/types/fieldType - 一个Node实例化一个FieldType
根据 @type到ResourceLoader里加载FieldType,注入 @name,获取./analyzer[ @type='query']作为此FiledType的query
分词器,获取./analyzer[not( @type)] | ./analyzer[ @type='index']作为此FieldType的index分词器,如果有任何一方
没有配置则index&query使用同一个分词器。将Node的属性除了 @name, @type的其他属性作用到FieldType上
b.schema/fields/field | schema/fields/dynamicField - 一个Node实例化一个SchemaField
根据 @type指定的类型到a.加载对应的FieldType. @name获取对应的FieldType,处理Index,Store,TermVector相关的属性这些SchemaField作为这个core下DOC的Field的定义
c.schema/similarity - 加载算分器
d.schema/defaultSearchField/text() – 默认查询字段
e.schema/solrQueryParser/ @defaultOperator – BooleanQuery的默认关系
f.schema/uniqueKey/text() – 唯一键
4.根据core的SolrConfig, CoreDescriptor, IndexSchema创建SolrCore
--------
a.获取solrConfig.maxWarmingSearchers –> maxWarmingSearchers
获取solrConfig.booleanQueryMaxClauseCount –> BooleanQuery.setMaxClauseCount
--------
b.获取solrConfig里配置的SolrEventListener插件,属性 @event=firstSearcher的放入链表firstSearcherListeners
属性 @event=newSearcher的放入链表newSearcherListeners
--------
c.获取solrConfig里配置的IndexDeletionPolicy插件,使用ResourceLoader加载类,如果是NamedListInitializedPlugin
使用其initArgs初始化,如果没配置使用SolrDeletionPolicy作为此core的索引文件删除决策者
--------
d.获取solrConfig里配置的DirectoryFactory插件,实例化->init(initArgs),如果没有使用StandardDirectoryFactory
获取solrConfig里配置的IndexReaderFactory插件,实例化->init(initArgs),如果没有使用StandardIndexReaderFactory
如果这个目录是JVM级别第一次打开&目录存在&solrConfig.unlockStartup则去看目录下的write.lock有没有因为进程的突然死亡而没释放掉,如果没有释放掉则释放这个锁
如果目录不存在则实例化一个SolrIndexWriter,再关闭它,这样做的目的是创建这个目录
--------
e.获取solrConfig里配置的QueryResponseWriter插件,这类插件是定义查询输出格式的,solr目前支持xml,json,python,php,javabin,raw,ruby等输出格式,加载完solrConfig定义的ResponseWriter后将solr支持的但没出现在solrconfig.xml里面的ResponseWriter添加到responseWriters中,如果solrconfig.xml没设置默认的ResponseWriter则用xml做默认格式
--------
f.获取solrConfig里配置的QueryParser插件,这类插件是定义query语句解析用的,solr提供的几种解析器接下来会提到
将solrconfig.xml定义的查询语法解析器和solr提供的解析器放入qParserPlugins中
--------
g.获取solrConfig里配置的SearchComponent插件,放入searchComponents中,solr提供了几个SearchComponent:
QueryComponent FacetComponent MoreLikeThisComponent HighlightComponent StatsComponent DebugComponent
如果solrConfig没有配置这些默认的则主动注入
--------
h.获取solrConfig里配置的UpdateRequestProcessorChain插件,这个插件作为此core处理UpdateRequest的责任链,如果
没有配置是默认的责任链是LogUpdateProcessorFactory -> RunUpdateProcessorFactory
--------
i.实例化RequestHandlers-此core的solr请求处理器SolrRequestHandler管理者,用solrcofig配置文件初始化
SolrRequestHandler的启动分为两种,一种是在系统启动阶段就初始化好;另一种是lazy启动模式,只有在第一次调用handleRequest时才去实例化&初始化,有属性 @startup=lazy
遍历SolrRequestHandler节点,对于lazy型的初始化LazyRequestHandlerWrapper(core, className, initArgs)
对于非lazy型的使用ResourceLoader加载实例再调用初始化函数init(initArgs)|init(PluginInfo)-PluginInfoInitialized
将创建的name -> RequestHandler映射注册到RequestHandlers.handlers上
SolrRequestHandler初始化主要做的事是初始化其几个属性: NameList-initArgs
SolrParams-defaults,appends,invariants
比较典型的两个RequestHandlers是处理查询请求的SearchHandler和处理更新请求的Handler
--------
j.打开一个SolrIndexSearcher,同时根据solrconfig.updateHandlerInfo实例化UpdateHandler,默认为
DirectUpdateHandler2
--------
k.在将全部需要加载的类都加载完后,solrCore还需要通知SolrCoreAware类对象core需要的类都实例化完了,SolrCoreAware可能需要做的初始化操作可以做了,solrCore会管理一个SolrCoreAware的链表,在使用ResourceLoader加载对象时判断类是否是SolrCoreAware,如果是加入到链表中等着回调。重点关注SearchHandler-用来处理查询请求的Handler,其在回调函数inform里
主要的做的事是:
SearchHandler是SolrRequestHandler的一种,用来处理搜索请求的,前面有提到过SearchComponent,之前core
已经把用户注入的SearchComponent和它支持的SearchComponent都加载好了,这些SearchComponent是
SearchHandler在处理搜索请求时干活的组件,如果这个Handler自己配置了组件则使用它配置的组件,如果没有配置则使用solr默认的搜索组件
------
加载完core后将core @name -> core的映射PUT到CoreContainer.cores上,CoreContainer类加载完成