`
damoqingquan
  • 浏览: 47818 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Solr1.3的启动过程分析三

阅读更多

在Solr1.3的启动过程分析二中,我们从Solr.xml文件中获得了xpath 为solr/cores/core的结点的表,这写节点对应多个的核。现在我们要看看如果对每个核进行初始化的。
    在CoreContainer的load(String dir, File configFile )方法中的for循环中,每次循环处理一个核的创建以及初始化。
    通过Node node = nodes.item(i);获得一个节点,下面的代码首先获得节点的name属性,然后去掉该塑性中,以及之后的部分,从而获得了一个核的名字。
    /////////////    
    String names = DOMUtil.getAttr(node, "name", null);
    List<String> aliases = StrUtils.splitSmart(names,',');
    String name = aliases.get(0);
    ////
    然后通过下面代码建立了核的描述器,这里要所一下什么是描述器,它就是一个包含核的名字、实例目录、配置文件名、模式文件名等等的类。
    ////
    CoreDescriptor p = new CoreDescriptor(this, name, DOMUtil.getAttr(node, "instanceDir", null));
    ////
    下面的代码读取solr.xml中的每个core节点的property子节点的内容,并通过这些类容来设置核描述器的coreProperties属性。
    ////
    
    p.setCoreProperties(readProperties(cfg, node));
    ////
    下面是读取core节点的config以及schema 属性,并用他们来设置核描述器的相应属性,它们存在的目的是用来指定这两个及其重要的配置文件的文件名的。代码就不必写出来了。
    现在来看最关键的部分,就是使用核描述器来建立核的部分,代码在这里比较简单,仅仅只有一句,但是内涵相当的丰富。先说完后面的再回头来看是如何通过描述器来建立核的。
   在建立核之后,就是注册,所谓注册就是将建立的核的引用put到CoreContainer中的cores并设置其名字。而且这里是先注册别名后注册非别 名的,别名注册前会使用core.open()方法,目的就是将引用计数增一。也许这里说的引用是对于一个的额外引用吧,所说在非别名注册之前没有 open()。
    顺便说一下,这里不知道是不是一个bug。在solr.xml的核的名字哪里使用逗号设立多个别名,注册时没有问题,但是在管理页面那里显示出来的名字确 是一样的。我猜想它的本意是希望在管理页面哪里能够看到一个核实例的多个别名的,但是显然这个目的没有达到。暂且不谈。
    这还有一个有趣的现象,我们在输入的日志文件中看到这样的信息:
    -----
    2008-12-19 13:02:47 org.apache.solr.core.SolrCore registerSearcher
    信息: [core0] Registered new searcher Searcher@8b8791 main
    2008-12-19 13:02:47 org.apache.solr.core.CoreContainer register
    信息: registering core: core0
    -----
    我们看到在输入注册日志信息之前输入了注册搜索器的信息,也就意味着这里建立了一个搜索器。如果我们在SolrCore core = create(p);之后任意打印一条信息,会发现这信息是在注册搜索器之前的,但是从打印信息到注册核信息整个过程中,我们无法通过跟踪代码找到注册搜 索器信息的来源。这是怎么回事情呢?
    后来我先到了会不会是多线程问题,于是我找到输入搜索器注册信息的位置,并在输入搜索器信息的代码前加了一个Thread.sleep(...);结果注册信息跑到后面很远,这也从而证明了我的猜测是正确的。
   实际上在每个核的实例建立的过程中会注册一个搜索器的,而且这个过程显然用到了多线程。
  
   好了,现在离开那个小小的意外来看看如何通过核描述器建立核的实例 的。
 
   在方法SoreContainer的create(CoreDescriptor dcore)方法的开始,首先进行一系列的处理,获得该核的实例目录的File对象,然后功过File对象获得该目录的绝对路径。
   然后通过下面的代码获得该核的主目录对应的加载器:
   ////
   SolrResourceLoader solrLoader = new SolrResourceLoader(instanceDir, libLoader, dcore.getCoreProperties());
    ////
    其中的libLoader是ClassLoader的对象,这里作为当前CoreContainer的属性。细节暂且不说。之后就是读取该目录下的配置文 件等来获得config(SolrConfig)和schema(IndexSchema)的实例,他们分别是当前核的配置信息和索引模式的载体。
   先来说说config的获得。
   ////
    SolrConfig config = new SolrConfig(solrLoader, dcore.getConfigName(), null);
   ////
   同样一句代码而已,但是内部却大有千秋。我们进去看看。
   该构造函数的原型如下:
    ////
    SolrConfig(SolrResourceLoader loader, String name, InputStream is)
    ////
    这里设计就是读取is中的内容(is如果为空,那就通过loader来找到一个默认的配置文件的流),然后通过w3c dom与xpath技术读取其中的配置属性并设置config对象中与之对应的属性的值。尽管内部做了很多的事情,但是输出的日志很少。这里有必要说明一 下在同一个核的IndexSchema与SolrConfig中的loader是同一个实例。
    接下来就是构建IndexSchema的实例,这里做的事情比较多了,从输入的日志文件可以看出来。
    ////
    IndexSchema schema = new IndexSchema(config, dcore.getSchemaName(), null);
    ////
    来看看构造函数的原型吧。
    ////
    IndexSchema(SolrConfig solrConfig, String name, InputStream is)
    ////
     第一个参数就是我们上面构建的config对象,第二个参数就是核描述器中指定的配置文件的文件名(也可以指定为null,此时内部将使用默认的名字),但是不包括路径。最后一个参数is与solrConfig的构造函数中的参数的用法是一样的。
    在构造方法的内部,首先将 solrConfig参数的引用赋予属性solrConfig,然后就是获得可用的模式文件的流lis。然后调用readSchema(lis);方法来 读取模式内容。通过下面的日志我们可以知道读取过程了。主要事情是从配置文件读取schema名字,创建其中需要的FieldType对象,例如 StrField,TextField扥等,这些类的对象包含了一个对应的field将会以何种方式进行处理,是索引,还是保存,是否进行分词,使用什么 工具进行分词等等。在下面日志中我们看到创建了连个FieldType对象,其中一个还加载了一个中文分词类 org.apache.solr.analysis.ChineseTokenizerFactory。最后就是指定默认搜索域,默认逻辑操作符号,默认 的唯一键。
     -------------------------
    2008-12-19 15:55:10 org.apache.solr.schema.IndexSchema readSchema
    信息: Reading Solr Schema
    2008-12-19 15:55:10 org.apache.solr.schema.IndexSchema readSchema
    信息: Schema name=example core one
    2008-12-19 15:55:10 org.apache.solr.util.plugin.AbstractPluginLoader load
    信息: created string: org.apache.solr.schema.StrField
    2008-12-19 15:55:10 org.apache.solr.util.plugin.AbstractPluginLoader load
    信息: created null: org.apache.solr.analysis.ChineseTokenizerFactory
    2008-12-19 15:55:10 org.apache.solr.util.plugin.AbstractPluginLoader load
    信息: created text: org.apache.solr.schema.TextField
    2008-12-19 15:55:10 org.apache.solr.schema.IndexSchema readSchema
    信息: default search field is question
    2008-12-19 15:55:10 org.apache.solr.schema.IndexSchema readSchema
    信息: query parser default operator is OR
    2008-12-19 15:55:10 org.apache.solr.schema.IndexSchema readSchema
    信息: unique key field: id
     --------------------------

     到了这里,两个配置文件都已经创建了,下面就是利用config与schema来创建核的实例。
     ////
     SolrCore core = new SolrCore(dcore.getName(), null, config, schema, dcore);
     return core;
     ////
     在内部做了什么呢?什么还是从日志文件着手来分析。
    -----------------
      2008-12-19 16:19:35 org.apache.solr.core.SolrCore <init>
    信息: [core0] Opening new SolrCore at D:\search_engine\multicore\core0/,     dataDir=D:\search_engine\multicore\core0/data/
    //在输入上面日志之前,SolrCore的name,coreDescriptor等属性进行了设置。
    2008-12-19 16:19:35 org.apache.solr.core.SolrCore <init>
    信息: JMX monitoring not detected for core: core0
    //没有在配置文件中jmx的相关信息,这里会建立一个默认的信息记录器infoRegistry
    2008-12-19 16:19:35 org.apache.solr.core.SolrCore parseListener
    信息: [core0] Searching for listeners: //listener[@event="firstSearcher"]
    //搜索并添加“第一个搜索器”监听器
    2008-12-19 16:19:35 org.apache.solr.core.SolrCore parseListener
    信息: [core0] Searching for listeners: //listener[@event="newSearcher"]
    //搜过并添加“新搜索器”监听器
    //上面两个监听器是通过 parseListeners();来添加的。
    //该方法内部代码为
    //firstSearcherListeners = parseListener("//listener[@event=\"firstSearcher\"]");
    //newSearcherListeners = parseListener("//listener[@event=\"newSearcher\"]");
    //他们通过搜索solrconfig.xml总的信息来获得两个监听器表。
    2008-12-19 16:19:35 org.apache.solr.util.plugin.AbstractPluginLoader load
    信息: created standard: org.apache.solr.handler.StandardRequestHandler
    //添加标准请求处理器
    2008-12-19 16:19:35 org.apache.solr.util.plugin.AbstractPluginLoader load
    信息: created /update: org.apache.solr.handler.XmlUpdateRequestHandler
     //添加xml更新请求处理器
    2008-12-19 16:19:35 org.apache.solr.util.plugin.AbstractPluginLoader load
    信息: created /admin/: org.apache.solr.handler.admin.AdminHandlers
     //添加管理处理器
     2008-12-19 16:19:36 org.apache.solr.search.SolrIndexSearcher <init>
    信息: Opening Searcher@9a44f1 main
     //打开主要处理器
   2008-12-19 16:19:36 org.apache.solr.update.DirectUpdateHandler2$CommitTracker    <init>
    信息: AutoCommit: disabled
    //设置提交跟踪器
    2008-12-19 16:19:36 org.apache.solr.handler.component.SearchHandler inform
    信息: Adding  component:org.apache.solr.handler.component.QueryComponent@13e6f83
    //添加查询组件
    2008-12-19 16:19:36 org.apache.solr.handler.component.SearchHandler inform
    信息: Adding  component:org.apache.solr.handler.component.FacetComponent@b0c5a
    //添加层面组件
2008-12-19 16:19:36 org.apache.solr.handler.component.SearchHandler inform
   信息: Adding  component:org.apache.solr.handler.component.MoreLikeThisComponent@158046e
    //添加相似查找组件
    2008-12-19 16:19:36 org.apache.solr.handler.component.SearchHandler inform
   信息: Adding  component:org.apache.solr.handler.component.HighlightComponent@18ad9a0
    //添加高亮显示组件
2008-12-19 16:19:36 org.apache.solr.handler.component.SearchHandler inform
    信息: Adding  debug   component:org.apache.solr.handler.component.DebugComponent@d5c653
    //添加调试组件


    至此,一个核就建立了。

敬请关注:http://www.lucas.gd.cn / 之Solr板块
----------------------------------------
原创文章:敬请著名出处http://www.lucas.gd.cn
作者:宋永维
email:lucas.song.cn@gmail.com

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics