SolrCloud分佈式集羣部署步驟

  • Solr及SolrCloud簡介

    Solr是一個獨立的企業級搜索應用服務器,它對外提供相似於Web-service的API接口。用戶能夠經過http請求,向搜索引擎服務器提交必定格式的XML文件,生成索引;也能夠經過Http Get操做提出查找請求,並獲得XML格式的返回結果。html

      SolrCloud是Solr4.0版本之後基於Solr和Zookeeper的分佈式搜索方案,它的主要思想是使用Zookeeper做爲集羣的配置信息中心。它有如下幾個特色:java

    1. 集中式的配置信息管理。
    2. 自動容錯。
    3. 近實時搜索。
    4. 查詢時自動負載均衡。
    5. 將索引存儲在HDFS上。
    6. 經過MR批量建立索引。

    更多關於SolrCloud的相關介紹可參考如下連接:linux

    1. http://www.chepoo.com/solrcloud-introduction.html
    2. http://www.cnblogs.com/phinecos/archive/2012/02/10/2345634.html
    3. https://cwiki.apache.org/confluence/display/solr/SolrCloud
  • 軟件包準備
  1. jdk-7u79-linux-x64.tar.gz
  2. apache-tomcat-7.0.62.tar.gz
  3. solr-5.2.1.tgz
  4. zookeeper-3.4.6.tar.gz
  • 服務器準備

    準備三臺服務器:web

    1. 192.168.1.131  
    2. 192.168.1.141 
    3. 192.168.1.146 
  • SolrCloud集羣搭建步驟

    • 服務器環境配置
      1. 配置主機名和IP映射,在3臺服務器的/etc/hosts文件中添加如下幾行:
        192.168.1.131 solr-cloud-master
        192.168.1.141 solr-cloud-slave1
        192.168.1.146 solr-cloud-slave2


        將文件同步到其它機器上。  
        scp /etc/hosts  solr-cloud-slave1:/etc/
        scp /ect/hosts  solr-cloud-slave2:/etc/
      2. 關閉防火牆,在生產環境中須要開放相應的端口。
        service     iptables stop
        chkconfig iptables off
    • 安裝文件目錄規劃
      1. JDK安裝目錄:/usr/local/lib
      2. Solr安裝目錄:/opt/SolrCloud/Solr/solr
      3. Solr配置文件目錄:/opt/SolrCloud/Solr/solr-config
      4. Solr數據文件目錄:/apps/data/solr-cores
      5. Zookeeper安裝目錄:/opt/SolrCloud/Zookeeper
      6. Zookeeper數據文件目錄:/apps/data/zookeeper/data
      7. Tomcat安裝目錄:/opt/SolrCloud/Tomcat
        除了安裝JDK的目錄不須要建立,其它目錄都須要進行建立。
    • 安裝JDK
      1. 解壓 jdk-7u79-linux-x64.tar.gz 到 /usr/local/lib/ 目錄下並重命名
      2. 在/etc/profile.d/ 目錄下建立一個shell腳本文件並添加一下內容:



        配置當即生效:
        source /etc/profile.d/jdk_env.sh

        輸入 java -version 檢測是否安裝成功

        也能夠直接修改/etc/profile文件,添加的內容都是同樣的。

        同步配置到其它機器:
        scp -r /usr/local/lib/jdk  solr-cloud-slave1:/usr/local/lib/
        scp  /etc/profile.d/jdk_env.sh  solr-cloud-slave1:/ect/profile.d/
        source  /etc/profile.d/jdk_env.sh
        
        scp -r /usr/local/lib/jdk  solr-cloud-slave2:/usr/local/lib/
        scp  /ect/profile.d/jdk_env.sh  solr-cloud-slave2:/etc/profile.d/
        source /etc/profile.d/jdk_env.sh
    • 安裝配置Zookeeper
      1. 解壓 zookeeper-3.4.6.tar.gz  到 /opt/SolrCloud/Zookeeper/ 目錄,並修改目錄全部者。


      2. 配置zookeeper
        cd /opt/SolrCloud/Zookeeper/zookeeper-3.4.6/conf
        cp zoo_sample.cfg zoo.cfg
      3. 修改zoo.cfg


      4. 參數詳解
        tickTime:該參數有默認值:3000,單位是毫秒(ms),能夠不配置,不支持系統屬性方式配置,參數tickTime用於配置Zookeeper中最小時間單元的長度,
        不少運行時的時間間隔都是使用tickTime的倍數來表示的。例如,Zookeeper中會話的最小超時時間默認是2*tickTime。

        initLimit:該參數有默認值:10,即表示是參數tickTime值的10倍,必須配置,且須要配置一個正整數,不支持系統屬性方式設置。該參數用於配置Leader服務器等待Follower啓動,
        並完成數據同步的時間。Follower服務器啓動過程當中,會與Leader創建鏈接並完成數據的同步,從而肯定本身對外提供服務的起始狀態。Leader服務器容許Follower在inittLimit時間內完成這個工做。一般狀況下,運維人員不用太在乎這個參數的配置,使用其默認值便可。但若是隨着Zookeeper集羣管理的數據量增大,Follower服務器在啓動的時候,從Leader上進行同步數據的時間也會相應變長,因而沒法在較短的時間完成數據同步。所以,在這種狀況下,有必要適當調大這個參數。

        syncLimit:該參數有默認值:5,即表示tickTime值得5倍,必須配置,且須要配置一個正整數,不支持系統屬性設置。該參數用於配置Leader服務器和Follower之間進行心跳檢測的最大延遲時間。在Zookeeper集羣運行過程當中,Leader服務器會與全部Follower進行心跳檢測來肯定該服務器是否存活。若是Leader服務器在syncLimit時間內沒法獲取到Follower的心跳檢測響應,那麼Leader就會認爲該Follower已經脫離了和本身的同步。

        dataDir:該參數無默認值,必須配置,不支持系統屬性方式設置,參數dataDir用於配置Zookeeper服務器存儲快照文件的目錄。默認狀況下,若是沒有配置參數dataLogDir,那麼事務日誌也會存儲在這個目錄中。考慮到事務日誌的寫性能直接影響Zookeeper總體的服務能力,所以建議同時經過參數dataLogDir來配置Zookeeper事務日誌的存儲目錄。

        dataLogDir:該參數有默認值,dataDir,能夠不配置,不支持系統屬性方式設置。參數dataLogDir用於配置Zookeeper服務器存儲事務日誌文件的目錄。默認狀況下,Zookeeper會將事務日誌文件和快照數據存儲在同一個目錄中,應儘可能將這二者的目錄區分開來,另外,若是條件容許,能夠將事務日誌的存儲配置在一個單獨的磁盤上。事務日誌記錄對於磁盤的性能要求很是高,爲了保證數據的一致性,Zookeeper在返回客戶端事務請求響應以前,必須將本次請求對應的事務日誌寫入到磁盤中。所以,事務日誌寫入的性能直接決定了Zookeeper在處理事務請求是的吞吐。

        clientPort:參數clientPort用於配置當前服務器對外的服務端口,客戶端會經過該端口和Zookeeper服務器創建鏈接,通常設置爲2181。每臺Zookeeper服務器均可以配置任意能夠的端口,同時,集羣中的因此服務器不須要保持clientPort端口一致。

        server.id=host:port:port :該參數沒有默認值,在單機模式下能夠不配置,不支持系統屬性方式設置。該參數用於配置組成Zookeeper集羣的機器列表,其中id即爲Server ID,與每臺服務器myid文件中的數字相對應。同時,在該參數中,會配置兩個端口:第一個端口用於指定Follower服務器與Leader進行運行時通訊和數據同步是所使用的端口,第二個端口則專門用於Leader選舉過程當中的投票通訊。在Zookeeper服務器啓動的時候,其會根據myid文件中配置的Server ID來肯定本身是哪臺服務器,並使用對於配置的端口來進行啓動。

      5. 同步Zookeeper的配置及相關目錄到其它兩臺機器:

        scp -r /opt/SolrCloud/Zookeeper/zookeeper-3.4.6/  solr-cloud-slave1:/opt/SolrCloud/Zookeeper/
        scp -r /apps/data/zookeeper/  solr-cloud-slave1:/apps/data/
        
        scp -r /opt/SolrCloud/Zookeeper/zookeeper-3.4.6/  solr-cloud-slave2:/opt/SolrCloud/Zookeeper/
        scp -r /apps/data/zookeeper/  solr-cloud-slave2:/apps/data/
      6. 建立myid文件,並寫入zoo.cfg中對於的Server ID:

        solr-cloud-master:


        solr-cloud-slave1:


        solr-cloud-slave2:


      7. 分別啓動三臺Zookeeper服務器:

        cd /opt/SolrCloud/Zookeeper/zookeeper-3.4.6/bin/
        ./zkServer.sh  start 


      8. 查看Zookeeper狀態

        solr-cloud-master:


        solr-cloud-slave1:


        solr-cloud-slave2:


      9. Zookeeper其它參考信息:

        Zookeeper官網:
        http://zookeeper.apache.org/doc/
        Zookeeper維基百科:
        https://cwiki.apache.org/confluence/display/ZOOKEEPER/Index;jsessionid=0B5F772DCFF3506613D26E3752F7D415
        Zookeeper技術博客:
        http://nileader.blog.51cto.com/1381108/d-16
    • SolrCloud分佈式集羣搭建
      1. 解壓 apache-tomcat-7.0.62.tar.gz ,解壓部署後的目錄爲:/opt/SolrCloud/Tomcat/apache-tomcat-7.0.62
      2. 解壓 solr-5.2.1.tgz ,並把solr.war解壓到/opt/SolrCloud/Solr/solr 目錄下。


      3. 將 solr-5.2.1/server/lib/ext/ 目錄下的jar包拷貝到 /opt/SolrCloud/Solr/solr/WEB-INF/lib/ 目錄下。
        cp /home/software/solr-5.2.1/server/lib/ext/*.jar /opt/SolrCloud/Solr/solr/WEB-INF/lib/
      4. 將 solr-5.2.1/server/solr/configsets/basic_configs/conf/ 目錄下的文件拷貝到 /opt/SolrCloud/Solr/solr-config/


      5. 將 solr-5.2.1/example/files/conf/ 目錄下的文件夾拷貝到 /opt/SolrCloud/Solr/solr-config/


      6. 將 /opt/SolrCloud/Solr/solr 目錄拷貝到 /opt/SolrCloud/Tomcat/apache-tomcat-7.0.62/webapps/ 目錄下。


      7. 將 solr-5.2.1/server/solr/ 目錄下的solr.xml文件拷貝到 /apps/data/solr-cores/ 目錄下,這是solr的核心配置文件。


      8. 修改 /apps/data/solr-cores/  目錄下的solr.xml,修改hostPort和Tomcat端口一致:


        同步配置到其它機器:
        scp /apps/data/solr-cores/solr.xml solr-cloud-slave1:/apps/data/solr-cores/
        scp /apps/data/solr-cores/solr.xml solr-cloud-slave2:/apps/data/solr-cores/
      9. 在 /opt/SolrCloud/Tomcat/apache-tomcat-7.0.62/conf/ 目錄下建立Catalina和localhost目錄。
         mkdir -p /opt/SolrCloud/Tomcat/apache-tomcat-7.0.62/conf/Catalina/localhost
      10. 在 /opt/SolrCloud/Tomcat/apache-tomcat-7.0.62/conf/Catalina/localhost/ 目錄下建立solr.xml,此爲Solr/home的配置文件。
        <?xml version="1.0" encoding="UTF-8"?>
        <Context docBase="/opt/SolrCloud/Tomcat/apache-tomcat-7.0.62/webapps/solr" debug="0" crossContext="true">
        <Environment name="solr/home" type="java.lang.String" value="/apps/data/solr-cores/" override="true"/>
        </Context>
      11.  修改 /opt/SolrCloud/Tomcat/apache-tomcat-7.0.62/bin/catalina.sh 加入如下內容:
        shell

      12. 將以上配置同步到其它服務器
        scp -r /opt/SolrCloud/Tomcat/apache-tomcat-7.0.62/  solr-cloud-slave1:/opt/SolrCloud/Tomcat/
        scp -r /opt/SolrCloud/Solr/   solr-cloud-slave1:/opt/SolrCloud/
        scp -r /apps/data/solr-cores/  solr-cloud-slave1:/apps/data/
        
        scp -r /opt/SolrCloud/Tomcat/apache-tomcat-7.0.62/  solr-cloud-slave2:/opt/SolrCloud/Tomcat/
        scp -r /opt/SolrCloud/Solr/   solr-cloud-slave2:/opt/SolrCloud/
        scp -r /apps/data/solr-cores/  solr-cloud-slave2:/apps/data/
      13. 上傳配置到Zookeeper:
        SolrCloud是經過Zookeeper集羣來保證配置文件的變動及時同步到各個節點上,因此,須要將配置文件上傳到Zookeeper集羣。
        solr配置文件目錄:/opt/SolrCloud/Solr/solr-config/
        執行如下操做:
         java -classpath .:/opt/SolrCloud/Tomcat/apache-tomcat-7.0.62/webapps/solr/WEB-INF/lib/* org.apache.solr.cloud.ZkCLI -cmd upconfig -zkhost solr-cloud-master:2181,solr-cloud-slave1:2181,solr-cloud-slave2:2181 -confdir /opt/SolrCloud/Solr/solr-config/ -confname solrconfig
      14. 校驗Zookeeper配置文件
        cd /opt/SolrCloud/Zookeeper/zookeeper-3.4.6/bin/
        ./zkCli.sh -server solr-cloud-master:2181

      15. 啓動Tomcat,先啓動solr-cloud-master機器上的tomcat:
        cd /opt/SolrCloud/Tomcat/apache-tomcat-7.0.62/bin/
        ./startup.sh

         啓動solr-cloud-slave1和solr-cloud-slave2機器上的Tomcat。apache

      16. 訪問http://solr-cloud-master:8080/solr/能夠看到下圖:
      17. 建立Collection及初始化Shard
        curl 'http://solr-cloud-master:8080/solr/admin/collections?action=CREATE&name=collection_1&numShards=3&replicationFactor=1'


        查看  /apps/data/solr-cores/  目錄:

        tomcat

      18. SolrCloud測試
        import java.io.IOException;
        import java.util.ArrayList;
        import java.util.Collection;
        import org.apache.commons.logging.Log;
        import org.apache.commons.logging.LogFactory;
        import org.apache.solr.client.solrj.SolrClient;
        import org.apache.solr.client.solrj.SolrQuery;
        import org.apache.solr.client.solrj.SolrServerException;
        import org.apache.solr.client.solrj.impl.CloudSolrClient;
        import org.apache.solr.client.solrj.impl.LBHttpSolrClient;
        import org.apache.solr.client.solrj.response.QueryResponse;
        import org.apache.solr.client.solrj.response.UpdateResponse;
        import org.apache.solr.common.SolrDocument;
        import org.apache.solr.common.SolrDocumentList;
        import org.apache.solr.common.SolrInputDocument;
        
        public class SolrCloudTest {
            public static final Log LOG = LogFactory.getLog(SolrCloudTest.class);
            private static CloudSolrClient cloudSolrClient;
            private  static LBHttpSolrClient solrClient;
        
            private static synchronized CloudSolrClient getCloudSolrServer(final String zkHost) {
                LOG.info("connection to : " + zkHost + "\n");
                if (cloudSolrClient == null) {
                    cloudSolrClient = new CloudSolrClient(zkHost);
                }
                return cloudSolrClient;
            }
        
            private void addIndex(SolrClient solrClient) {
                try {
                    Collection<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
                    for (int i = 0; i <= 200; i++) {
                        SolrInputDocument doc = new SolrInputDocument();
                        String key = "";
                        key = String.valueOf(i);
                        doc.addField("id", key);
                        doc.addField("test_s", key + "value");
                        docs.add(doc);
                    }
                    LOG.info("docs info:" + docs + "\n");
                    solrClient.add(docs);
                    solrClient.commit();
                } catch (SolrServerException e) {
                    System.out.println("Add docs Exception !!!");
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    System.out.println("Unknowned Exception!!!!!");
                    e.printStackTrace();
                }
            }
            
            public void search(CloudSolrClient cloudSolrClient, String Str) {          
                  SolrQuery query = new SolrQuery();
                  query.setRows(20);
                  query.setQuery(Str);    
                  try {  
                       LOG.info("query string: "+ Str);
                       System.out.println("query string: "+ Str);
                    QueryResponse response = cloudSolrClient.query(query);    
                    SolrDocumentList docs = response.getResults();
                    System.out.println(docs);
                    System.out.println(docs.size());
                    System.out.println("doc num:" + docs.getNumFound());    
                    System.out.println("elapse time:" + response.getQTime());            
                    for (SolrDocument doc : docs) {    
                      String area = (String) doc.getFieldValue("test_s");    
                      String id = (String) doc.getFieldValue("id");    
                      System.out.println("id: " + id);    
                      System.out.println("tt_s: " + area);    
                      System.out.println();    
                    }    
                  } catch (SolrServerException e) {    
                    e.printStackTrace();    
                  } catch(Exception e) {    
                    e.printStackTrace();    
                  }    
                } 
            
            public  void deleteSolrData(String solrUrl) {
                try {
                    solrClient = new LBHttpSolrClient(solrUrl);
                    UpdateResponse res = solrClient.deleteByQuery("*:*");
                    System.out.println(res.getStatus());
                    solrClient.commit();
                    LOG.info("Delete Success!");
                } catch (SolrServerException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
            
             public static void main(String[] args) throws IOException {    
                     final String solrUrl = "http://solr-cloud-master:8080/solr/collection_1";
                    final String zkHost = "192.168.1.131:2181";         
                    final String  defaultCollection = "collection_1";    
                    final int  zkClientTimeout = 10000;    
                    final int zkConnectTimeout = 10000;                      
                    CloudSolrClient cloudSolrClient  = getCloudSolrServer(zkHost);                     
                    cloudSolrClient.setDefaultCollection(defaultCollection);    
                    cloudSolrClient.setZkClientTimeout(zkClientTimeout);    
                    cloudSolrClient.setZkConnectTimeout(zkConnectTimeout); 
                    try{
                        cloudSolrClient.connect();
                      System.out.println("connect solr cloud zk sucess");                 
                    } catch (Exception e){    
                       LOG.error("connect to collection "+defaultCollection+" error\n");
                       System.out.println("error message is:"+e);
                       e.printStackTrace();
                       System.exit(1);
                    }
                    SolrCloudTest solrCloudTest = new SolrCloudTest();
                    try{
                        solrCloudTest.addIndex(cloudSolrClient);
                    } catch(Exception e){
                       e.printStackTrace();
                    }
                    solrCloudTest.search(cloudSolrClient, "id:*");
        //            solrCloudTest.deleteSolrData(solrUrl);
                    cloudSolrClient.close();    
                }          
        }
  • 總結

   Solr5.x版本和Solr4.x的版本在安裝上發生了比較大的變化,另外API操做上也發生了比較大的變化,安裝相對來講比較簡單,最大的難點在於對其進行性能方面的優化,在進行壓力測試中發現,持續對solr集羣進行操做會出現服務不可用的異常,緣由目前尚未找到,有時還會出現Zookeeper集羣服務異常致使數據插入失敗。針對這些問題都須要後續不斷地進行深刻的研究後,才能得出結論或解決方案。服務器

    本文參考了:http://www.tuicool.com/articles/AJR3Mvsession

相關文章
相關標籤/搜索