上文写到Solr的启动过程是在SolrDispatchFilter的init()里实现,当Tomcat启动时候会自动调用init();

Solr的启动主要在 this.cores = createCoreContainer();语句中实现。

/**
*初始化,当tomcat启动时候开始初始化,其中主要调用createCoreContainer来实现Solr的初始化
*/
public void init(FilterConfig config) throws ServletException
{
log.info("SolrDispatchFilter.init()"); try {
// web.xml configuration
this.pathPrefix = config.getInitParameter( "path-prefix" ); this.cores = createCoreContainer();
log.info("user.dir=" + System.getProperty("user.dir"));
}
catch( Throwable t ) {
// catch this so our filter still works
log.error( "Could not start Solr. Check solr/home property and the logs");
SolrCore.log( t );
if (t instanceof Error) {
throw (Error) t;
}
} log.info("SolrDispatchFilter.init() done");
}

Solr的启动过程主要包括:

1. 获取SolrHome:分别先后通过JNDI,System property,default directory三种方式尝试获取
2. 实例化启动过程中使用的类加载器SolrResourceLoader
3. 加载solrhome下的solr.xml文件,封装为ConfigSolr
4. 实例化一个CoreContainer,通过CoreContainer来加载cores
5. 遍历SolrHome,当寻找到含有core.properties的文件夹,则作为一个core
6. 多线程加载cores
7. 加载每个core时先加载solrconfig.xml封装为SolrConfig
8. 再加载schema.xml封装为IndexSchema
9. 最后实例化SolrCore

以下是createCoreContainer()实现代码,该函数就包含了以上的启动过程。

   /**
* Override this to change CoreContainer initialization
* @return a CoreContainer to hold this server's cores
*/
protected CoreContainer createCoreContainer() {
SolrResourceLoader loader = new SolrResourceLoader(SolrResourceLoader.locateSolrHome());
ConfigSolr config = loadConfigSolr(loader);
CoreContainer cores = new CoreContainer(loader, config);
cores.load();
return cores;
}

1. 获取SolrHome信息

Solr通过三种方式来获取SolrHome,分别是JNDI,System property,以及当前路径。

JNDI的java:comp/env/solr/home的获取,主要通过在tomcat/conf/Catalina/localhost目录下新建solr.xml。Tomcat启动的时候就会该目录下自动获取  SolrHome的信息.

System property的SolrHome获取是直接在tomcat启动脚本catalina.sh中加入set JAVA_OPTS -Dsolr.solr.home=/Users/rcf/workspace/java/solr 。

最后的获取SolrHome的方式就是在当前目录下查找。

   /**
* Determines the solrhome from the environment.
* Tries JNDI (java:comp/env/solr/home) then system property (solr.solr.home);
* if both fail, defaults to solr/
* @return the instance directory name
*/
/**
* Finds the solrhome based on looking up the value in one of three places:
* <ol>
* <li>JNDI: via java:comp/env/solr/home</li>
* <li>The system property solr.solr.home</li>
* <li>Look in the current working directory for a solr/ directory</li>
* </ol>
*
* The return value is normalized. Normalization essentially means it ends in a trailing slash.
* @return A normalized solrhome
* @see #normalizeDir(String)
*/
public static String locateSolrHome() { String home = null;
// Try JNDI
try {
Context c = new InitialContext();
home = (String)c.lookup("java:comp/env/"+project+"/home");
log.info("Using JNDI solr.home: "+home );
} catch (NoInitialContextException e) {
log.info("JNDI not configured for "+project+" (NoInitialContextEx)");
} catch (NamingException e) {
log.info("No /"+project+"/home in JNDI");
} catch( RuntimeException ex ) {
log.warn("Odd RuntimeException while testing for JNDI: " + ex.getMessage());
} // Now try system property
if( home == null ) {
String prop = project + ".solr.home";
home = System.getProperty(prop);
if( home != null ) {
log.info("using system property "+prop+": " + home );
}
} // if all else fails, try
if( home == null ) {
home = project + '/';
log.info(project + " home defaulted to '" + home + "' (could not find system property or JNDI)");
}
return normalizeDir( home );
}
 <Context docBase="/Users/rcf/workspace/java/tomcat/apache-tomcat-8.0.9/webapps/solr.war" debug="0" crossContext="true" >
<Environment name="solr/home" type="java.lang.String" value="/Users/rcf/workspace/java/solr" override="true" />
</Context>

获取完SolrHome后,就会实例化SolrResourceLoader。因为传进去的parent是null,所以parents是ContextClassLoader,并且加载了SolrHome/lib/下的文件.

   /**
* <p>
* This loader will delegate to the context classloader when possible,
* otherwise it will attempt to resolve resources using any jar files
* found in the "lib/" directory in the specified instance directory.
* </p>
*
* @param instanceDir - base directory for this resource loader, if null locateSolrHome() will be used.
* @see #locateSolrHome
*/
public SolrResourceLoader( String instanceDir, ClassLoader parent, Properties coreProperties )
{
if( instanceDir == null ) {
this.instanceDir = SolrResourceLoader.locateSolrHome();
log.info("new SolrResourceLoader for deduced Solr Home: '{}'",
this.instanceDir);
} else{
this.instanceDir = normalizeDir(instanceDir);
log.info("new SolrResourceLoader for directory: '{}'",
this.instanceDir);
} this.classLoader = createClassLoader(null, parent);
addToClassLoader("./lib/", null, true);
reloadLuceneSPI();
this.coreProperties = coreProperties;
}
   /**
* Convenience method for getting a new ClassLoader using all files found
* in the specified lib directory.
*/
static URLClassLoader createClassLoader(final File libDir, ClassLoader parent) {
if ( null == parent ) {
parent = Thread.currentThread().getContextClassLoader();
}
return replaceClassLoader(URLClassLoader.newInstance(new URL[0], parent),
libDir, null);
}
 1   /**
* Adds every file/dir found in the baseDir which passes the specified Filter
* to the ClassLoader used by this ResourceLoader. This method <b>MUST</b>
* only be called prior to using this ResourceLoader to get any resources, otherwise
* it's behavior will be non-deterministic. You also have to {link @reloadLuceneSPI}
* before using this ResourceLoader.
*
* <p>This method will quietly ignore missing or non-directory <code>baseDir</code>
* folder.
*
* @param baseDir base directory whose children (either jars or directories of
* classes) will be in the classpath, will be resolved relative
* the instance dir.
* @param filter The filter files must satisfy, if null all files will be accepted.
* @param quiet Be quiet if baseDir does not point to a directory or if no file is
* left after applying the filter.
*/
void addToClassLoader(final String baseDir, final FileFilter filter, boolean quiet) {
File base = FileUtils.resolvePath(new File(getInstanceDir()), baseDir);
if (base != null && base.exists() && base.isDirectory()) {
File[] files = base.listFiles(filter);
if (files == null || files.length == 0) {
if (!quiet) {
log.warn("No files added to classloader from lib: "
+ baseDir + " (resolved as: " + base.getAbsolutePath() + ").");
}
} else {
this.classLoader = replaceClassLoader(classLoader, base, filter);
}
} else {
if (!quiet) {
log.warn("Can't find (or read) directory to add to classloader: "
+ baseDir + " (resolved as: " + base.getAbsolutePath() + ").");
}
}
}

Solr4.8.0源码分析(2)之Solr的启动(一)的更多相关文章

  1. Solr4.8.0源码分析(7)之Solr SPI

    Solr4.8.0源码分析(7)之Solr SPI 查看Solr源码时候会发现,每一个package都会由对应的resources. 如下图所示: 一时对这玩意好奇了,看了文档以后才发现,这个serv ...

  2. Solr4.8.0源码分析(1)之Solr的Servlet

    Solr是作为一个Servlet运行在Tomcat里面的,可以查看Solr的web.xml. 1.web.xml配置 由web.xml可以看出,基本上所有Solr的操作都是在SolrDispatchF ...

  3. Solr4.8.0源码分析(9)之Lucene的索引文件(2)

    Solr4.8.0源码分析(9)之Lucene的索引文件(2) 一. Segments_N文件 一个索引对应一个目录,索引文件都存放在目录里面.Solr的索引文件存放在Solr/Home下的core/ ...

  4. Solr4.8.0源码分析(25)之SolrCloud的Split流程

    Solr4.8.0源码分析(25)之SolrCloud的Split流程(一) 题记:昨天有位网友问我SolrCloud的split的机制是如何的,这个还真不知道,所以今天抽空去看了Split的原理,大 ...

  5. Solr4.8.0源码分析(24)之SolrCloud的Recovery策略(五)

    Solr4.8.0源码分析(24)之SolrCloud的Recovery策略(五) 题记:关于SolrCloud的Recovery策略已经写了四篇了,这篇应该是系统介绍Recovery策略的最后一篇了 ...

  6. Solr4.8.0源码分析(23)之SolrCloud的Recovery策略(四)

    Solr4.8.0源码分析(23)之SolrCloud的Recovery策略(四) 题记:本来计划的SolrCloud的Recovery策略的文章是3篇的,但是没想到Recovery的内容蛮多的,前面 ...

  7. Solr4.8.0源码分析(22)之SolrCloud的Recovery策略(三)

    Solr4.8.0源码分析(22)之SolrCloud的Recovery策略(三) 本文是SolrCloud的Recovery策略系列的第三篇文章,前面两篇主要介绍了Recovery的总体流程,以及P ...

  8. Solr4.8.0源码分析(21)之SolrCloud的Recovery策略(二)

    Solr4.8.0源码分析(21)之SolrCloud的Recovery策略(二) 题记:  前文<Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一)>中提 ...

  9. Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一)

    Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一) 题记: 我们在使用SolrCloud中会经常发现会有备份的shard出现状态Recoverying,这就表明Solr ...

随机推荐

  1. input页面居中,软键盘覆盖input

    input框位于底部 对于ios的软键盘遮盖input输入框问题,网上已经有了一些解决办法,无非就是改变布局,再加scroll.js插件实现滚动, input框位于顶部 这种情况不会出现问题, inp ...

  2. Python随机生成验证码的两种方法

    Python随机生成验证码的方法有很多,今天给大家列举两种,大家也可以在这个基础上进行改造,设计出适合自己的验证码方法方法一:利用range Python随机生成验证码的方法有很多,今天给大家列举两种 ...

  3. C# 对JS编码/解码进行转换

    public static class Extension { #region [编码/解码统一转换] /// <summary> /// /// </summary> /// ...

  4. 从零开始写一个Tomcat(叁)--请求解析

    挖坑挖了这么长时间也该继续填坑了,上文书讲到从零开始写一个Tomcat(贰)--建立动态服务器,讲了如何让服务器解析请求,分离servlet请求和静态资源请求,读取静态资源文件输出或是通过URLCla ...

  5. docker入门(二)

    打造自己的镜像 首先我们启动busybox镜像为容器,在该容器中安装一个小工具,再将这个容器保存为新的镜像 首先我们下载一个镜像,再启动容器 [root@centos ~]# docker pull ...

  6. JDK5-自动拆装箱

    拆装箱:在基本类型与其对应的引用类型之间转换 装箱:Integer iObj = 5; 拆箱:int i = 5 + iObj; 装箱时,一个字节以内的数据在一个常量池中(小整数的使用频率高),即-1 ...

  7. discuz! X3.2 自定义后台门户模块模板里的标签

    这里只提供对源码的修改, 至于插件, 暂不考虑... 想在首页里展示一些自定义字段的内容, 奈何dz无此功能, 无奈去扒源码. 首先切到 source 文件夹下 1. 在 class/block/po ...

  8. Linux入门基础教程

    转载自:http://www.centoscn.com/CentOS/2015/0528/5555.html 1. 1      Linux操作系统简介 Linux是一套免费使用和自由传播的类Unix ...

  9. Python开发【第九篇】:HTML (二)

    python[第十四篇]HTML基础 时间:2016-08-08 20:57:27      阅读:49      评论:0      收藏:0      [点我收藏+] 标签: 什么是HTML? H ...

  10. 进程外session(session保存在sqlserver)

    .Session保存在SQLServer中配置方法 )运行.NetFramework安装目录下对应版本的aspnet_regsql.exe 来创建相关的数据库.表和存储过程等,比如: C:\Windo ...