• Solr4.8.0源码分析(2)之Solr的启动(一)


    上文写到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()实现代码,该函数就包含了以上的启动过程。

     1   /**
     2    * Override this to change CoreContainer initialization
     3    * @return a CoreContainer to hold this server's cores
     4    */
     5   protected CoreContainer createCoreContainer() {
     6     SolrResourceLoader loader = new SolrResourceLoader(SolrResourceLoader.locateSolrHome()); 
     7     ConfigSolr config = loadConfigSolr(loader);
     8     CoreContainer cores = new CoreContainer(loader, config);
     9     cores.load();
    10     return cores;
    11   }

     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的方式就是在当前目录下查找。

     1   /**
     2    * Determines the solrhome from the environment.
     3    * Tries JNDI (java:comp/env/solr/home) then system property (solr.solr.home);
     4    * if both fail, defaults to solr/
     5    * @return the instance directory name
     6    */
     7   /**
     8    * Finds the solrhome based on looking up the value in one of three places:
     9    * <ol>
    10    *  <li>JNDI: via java:comp/env/solr/home</li>
    11    *  <li>The system property solr.solr.home</li>
    12    *  <li>Look in the current working directory for a solr/ directory</li> 
    13    * </ol>
    14    *
    15    * The return value is normalized.  Normalization essentially means it ends in a trailing slash.
    16    * @return A normalized solrhome
    17    * @see #normalizeDir(String)
    18    */
    19   public static String locateSolrHome() {
    20 
    21     String home = null;
    22     // Try JNDI
    23     try {
    24       Context c = new InitialContext();
    25       home = (String)c.lookup("java:comp/env/"+project+"/home");
    26       log.info("Using JNDI solr.home: "+home );
    27     } catch (NoInitialContextException e) {
    28       log.info("JNDI not configured for "+project+" (NoInitialContextEx)");
    29     } catch (NamingException e) {
    30       log.info("No /"+project+"/home in JNDI");
    31     } catch( RuntimeException ex ) {
    32       log.warn("Odd RuntimeException while testing for JNDI: " + ex.getMessage());
    33     } 
    34     
    35     // Now try system property
    36     if( home == null ) {
    37       String prop = project + ".solr.home";
    38       home = System.getProperty(prop);
    39       if( home != null ) {
    40         log.info("using system property "+prop+": " + home );
    41       }
    42     }
    43     
    44     // if all else fails, try 
    45     if( home == null ) {
    46       home = project + '/';
    47       log.info(project + " home defaulted to '" + home + "' (could not find system property or JNDI)");
    48     }
    49     return normalizeDir( home );
    50   }
    1 <Context docBase="/Users/rcf/workspace/java/tomcat/apache-tomcat-8.0.9/webapps/solr.war" debug="0" crossContext="true" > 
    2     <Environment name="solr/home" type="java.lang.String" value="/Users/rcf/workspace/java/solr" override="true" />
    3 </Context>  

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

     1   /**
     2    * <p>
     3    * This loader will delegate to the context classloader when possible,
     4    * otherwise it will attempt to resolve resources using any jar files
     5    * found in the "lib/" directory in the specified instance directory.
     6    * </p>
     7    *
     8    * @param instanceDir - base directory for this resource loader, if null locateSolrHome() will be used.
     9    * @see #locateSolrHome
    10    */
    11   public SolrResourceLoader( String instanceDir, ClassLoader parent, Properties coreProperties )
    12   {
    13     if( instanceDir == null ) {
    14       this.instanceDir = SolrResourceLoader.locateSolrHome();
    15       log.info("new SolrResourceLoader for deduced Solr Home: '{}'", 
    16                this.instanceDir);
    17     } else{
    18       this.instanceDir = normalizeDir(instanceDir);
    19       log.info("new SolrResourceLoader for directory: '{}'",
    20                this.instanceDir);
    21     }
    22     
    23     this.classLoader = createClassLoader(null, parent);
    24     addToClassLoader("./lib/", null, true);
    25     reloadLuceneSPI();
    26     this.coreProperties = coreProperties;
    27   }
     1   /**
     2    * Convenience method for getting a new ClassLoader using all files found
     3    * in the specified lib directory.
     4    */
     5   static URLClassLoader createClassLoader(final File libDir, ClassLoader parent) {
     6     if ( null == parent ) {
     7       parent = Thread.currentThread().getContextClassLoader();
     8     }
     9     return replaceClassLoader(URLClassLoader.newInstance(new URL[0], parent),
    10                               libDir, null);
    11   }

    1
    /** 2 * Adds every file/dir found in the baseDir which passes the specified Filter 3 * to the ClassLoader used by this ResourceLoader. This method <b>MUST</b> 4 * only be called prior to using this ResourceLoader to get any resources, otherwise 5 * it's behavior will be non-deterministic. You also have to {link @reloadLuceneSPI} 6 * before using this ResourceLoader. 7 * 8 * <p>This method will quietly ignore missing or non-directory <code>baseDir</code> 9 * folder. 10 * 11 * @param baseDir base directory whose children (either jars or directories of 12 * classes) will be in the classpath, will be resolved relative 13 * the instance dir. 14 * @param filter The filter files must satisfy, if null all files will be accepted. 15 * @param quiet Be quiet if baseDir does not point to a directory or if no file is 16 * left after applying the filter. 17 */ 18 void addToClassLoader(final String baseDir, final FileFilter filter, boolean quiet) { 19 File base = FileUtils.resolvePath(new File(getInstanceDir()), baseDir); 20 if (base != null && base.exists() && base.isDirectory()) { 21 File[] files = base.listFiles(filter); 22 if (files == null || files.length == 0) { 23 if (!quiet) { 24 log.warn("No files added to classloader from lib: " 25 + baseDir + " (resolved as: " + base.getAbsolutePath() + ")."); 26 } 27 } else { 28 this.classLoader = replaceClassLoader(classLoader, base, filter); 29 } 30 } else { 31 if (!quiet) { 32 log.warn("Can't find (or read) directory to add to classloader: " 33 + baseDir + " (resolved as: " + base.getAbsolutePath() + ")."); 34 } 35 } 36 }
    转载请注明地址http://www.cnblogs.com/rcfeng/
  • 相关阅读:
    scala list
    scala 数组 基本类型
    oracle 索引 。其中全文检索最变态
    友盟分享(微信分享,微博分享,Facebook分享)
    iOS文字描边
    字符串限制条件
    IOS开发之格式化日期时间
    动态获取Textfield输入的内容
    iOS 微信分享 朋友圈
    iPhone屏幕尺寸、分辨率及适配
  • 原文地址:https://www.cnblogs.com/rcfeng/p/3911482.html
Copyright © 2020-2023  润新知