solr+zookeeper集羣搭建

一、前期準備工作

相關工具:
1.虛擬機(VMware)
2.tomcat7 64位  下載地址:http://tomcat.apache.org/download-70.cgi
3.centos6.4  64位
4.linux下的64位jdk安裝包,版本爲6或以上
5. solr-4.3.1.tgz包  下載:http://archive.apache.org/dist/lucene/solr/
6. zookeeper-3.4.5.tar.gz包  下載:http://hadoop.apache.org/zookeeper/releases.html

環境:
虛擬機環境centos6.4 64位系統 三臺硬盤50G 內存的虛擬機 網卡模式是NAT(測試環境推薦使用NAT,實際生產時可使用橋接以便外網訪問)

 

環境搭建

1.安裝虛擬機 (這裏不做贅述)。
2.虛擬機安裝成功後,用java –version命令查看是否自帶OpenJdk,若有則卸載此jdk。(這裏不做贅述)
3.爲虛擬機安裝jdk(這裏不做贅述)。
4.爲每臺虛擬機配置結點映射(若不使用域名此步驟可忽略):以虛擬機master爲例,修改 /etc/hosts 文件如下圖



 

其中後面的master slave1和slave2是作爲別名以便於與network中的HOSTNAME做映射。    
ZooKeeper集羣中具有兩個關鍵的角色:Leader和Follower。
集羣中所有的結點作爲一個整體對分佈式應用提供服務,集羣中每個結點之間 都互相連接,
所以,在配置的ZooKeeper集羣的時候,每一個結點的host到IP地址的映射都要配置上集羣中其它結點的映射信息。            
ZooKeeper採用一種稱爲Leader election的選舉算法。在整個集羣運行過程中,只有一個Leader,其他的都是Follower,
如果ZooKeeper集羣在運行過程中 Leader出了問題,系統會採用該算法重新選出一個Leader。
因此,各個結點之間要能夠保證互相連接,必須配置上述映射。
ZooKeeper集羣啓動的時候,會首先選出一個Leader,在Leader election過程中,某一個滿足選舉算的結點就能成爲Leader。

整個集羣的架構可以參考http://zookeeper.apache.org/doc/trunk/zookeeperOver.html#sc_designGoals

5.修改/etc/sysconfig裏的network配置文件(這裏以master爲例):HOSTNAME=master

 

二、正式solrCloud集羣搭建

 

Zookeeper Distributed模式集羣搭建

 

首先要明確的是,ZooKeeper集羣是一個獨立的分佈式協調服務集羣,“獨立”的含義就是說,
如果想使用ZooKeeper實現分佈式應用的協調與管 理,簡化協調與管理,任何分佈式應用都可以使用,
這就要歸功於Zookeeper的數據模型(Data Model)和層次命名空間(Hierarchical Namespace)結構,
詳細可以參考http://zookeeper.apache.org/doc/trunk/zookeeperOver.html。在設計你的分佈式應用協調服務時,
首要的就是考慮如何組織層次命名空間。
Zookeeper集羣的機器個數推薦是奇數臺,半數機器掛掉,服務是可以正常提供的


現在以master爲例搭建zookeeper集羣:
1.在根目錄下新建soft文件夾,將zookeeper.3.4.5.tar.gz包上傳至soft目錄下並解壓縮.
2.新建/soft/zookeeper-data 文件夾  //zookeeper的數據存儲位置
  新建/soft/zookeeper-data/logs 文件夾  // zookeeper的日誌文件位置

3.將/soft/ zookeeper-3.4.5/ conf 下的zoo_sample.cfg文件名改爲zoo.cfg 並修改zoo.cfg文件如下圖:



 或者使用域名



 tickTime:這個時間是作爲 Zookeeper 服務器之間或客戶端與服務器之間維持心跳的時間間隔,也就是每個 tickTime 時間就會發送一個心跳。      
initLimit:這個配置項是用來配置 Zookeeper 接受客戶端(這裏所說的客戶端不是用戶連接 Zookeeper 服務器的客戶端,而是 Zookeeper服務器集羣中連接到 Leader 的 Follower 服務器)初始化連接時最長能忍受多少個心跳時間間隔數。當已經超過 10 個心跳的時間(也就是tickTime)長度後 Zookeeper 服務器還沒有收到客戶端的返回信息,那麼表明這個客戶端連接失敗。總的時間長度就是5*2000=10秒。
syncLimit:這個配置項標識 Leader 與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個 tickTime 的時間長度,總的時間長度就是 2*2000=4 秒
dataDir:顧名思義就是 Zookeeper 保存數據的目錄,默認情況下,Zookeeper 將寫數據的日誌文件也保存在這個目錄裏。
dataLogDir: Zookeeper的日誌文件位置。
server.A=B:C:D:其中 A 是一個數字,表示這個是第幾號服務器;B是這個服務器的 ip 地址;C 表示的是這個服務器與集羣中的 Leader服務器交換信息的端口;D 表示的是萬一集羣中的 Leader 服務器掛了,需要一個端口來重新進行選舉,選出一個新的 Leader,而這個端口就是用來執行選舉時服務器相互通信的端口。如果是僞集羣的配置方式,由於 B 都是一樣,所以不同的 Zookeeper 實例通信端口號不能一樣,所以要給它們分配不同的端口號。
clientPort:這個端口就是客戶端連接 Zookeeper 服務器的端口,Zookeeper 會監聽這個端口,接受客戶端的訪問請求。

 

4.配置完成後把配置發送到其他兩臺機子
5.分別在每臺機器的/soft/zookeeper-data 下創建myid文件存儲該機器的標識碼 比如server.1 的標識碼就是 “1” myid文件的內容就一行: 1
6.配置完成後依次啓動(注意啓動前一定要關閉防火牆,否則zookeeper查看啓動後的狀態會查看不到各自的角色)master、 slave1和slave2的zookeeper服務,啓動成功後查看啓動狀態如下:

master:



slave1: 



 slave2:



 
通過狀態查詢結果可以看出,slave1被選作爲了Leader其餘的兩個結點是Follower。
另外,可以通過客戶端腳本,連接到ZooKeeper集羣上。對於客戶端來說,ZooKeeper是一個整體(ensemble),
連接到ZooKeeper集羣實際上感覺在獨享整個集羣的服務,所以,你可以在任何一個結點上建立到服務集羣的連接。

 

Solrcloud分佈式集羣搭建

 

1.將apache-tomcat-7.0.37-windows-x64包上傳至soft下並解壓
2.在本地解壓solr-4.3.1.tgz包,解壓後找到solr-4.3.1\example\webapps\solr.war並將solr.war解壓至solr文件夾。
3.將solr-4.3.1\example\lib\ext下的jar包放到solr\WEB-INF\lib下。
4.(以其中的一臺虛擬機master爲例)創建/usr/local/solrcloud目錄 /usr/local/solrcloud/config-files目錄和/usr/local/solrcloud/solr-lib目錄。
5.在/usr/local/solrcloud/config-files目錄下放置apache-solr-4.3.1\example\solr\collection1\conf 下的所有文件。
6.在目錄/usr/local/solrcloud/solr-lib目錄下放置solr\WEB-INF\lib下的所有jar包。
7.將solr上傳至/soft/apache-tomcat-7.0.37/webapps下。
8.添加停詞,擴展詞,ik分詞器:下載IKAnalyzer包,將IKAnalyzer解壓文件夾下的stopword.dic和IKAnalyzer.cfg.xml複製到tomcat/webapps/solr/WEB-INF/classes下,再新建一個ext.dic,裏面的格式和stopword.dic一致。並修改IKAnalyzer.cfg.xml如下所示,可以配置多個停止詞或者擴展詞庫文件(具體詳細內容可見http://lucien-zzy.iteye.com/blog/2002087)。

 

 

Xml代碼  收藏代碼
  1. <properties>     
  2.     <comment>IK Analyzer 擴展配置</comment>   
  3.     <!--用戶可以在這裏配置自己的擴展字典 -->   
  4.     <entry key="ext_dict">ext.dic;</entry>    
  5.     <!--用戶可以在這裏配置自己的擴展停止詞字典-->   
  6.     <entry key="ext_stopwords">stopword.dic;stopword_chinese.dic;</entry>    
  7. </properties>   

  

 Ik分詞器配置見http://lucien-zzy.iteye.com/blog/2002087

 

9.創建solr的數據目錄/soft/solr-cores並在該目錄下生成solr.xml 這是solr的核配置文件

 

Xml代碼  收藏代碼
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <solr persistent="true">  
  3. <logging enabled="true">  
  4. <watcher size="100" threshold="INFO" />  
  5. </logging>  
  6. <cores defaultCoreName="collection1" adminPath="/admin/cores" host="${host:}" hostPort="8080" hostContext="${hostContext:solr}" zkClientTimeout="${zkClientTimeout:15000}">  
  7. </cores>  
  8. </solr>  

 這裏,我們並沒有配置任何的core元素,這個等到整個配置安裝完成之後,通過SOLR提供的REST接口,來實現Collection以及Shard的創建,從而來更新這些配置文件。

 

 

10.創建/soft/apache-tomcat-7.0.37/ conf/ Catalina 目錄 和/soft/apache-tomcat-7.0.37/conf/Catalina/localhost目錄

 

11.在/soft/apache-tomcat-7.0.37/conf/Catalina/localhost 下創建solr.xml

 

Xml代碼  收藏代碼
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <Context docBase="/soft/apache-tomcat-7.0.37/webapps/solr" debug="0" crossContext="true">  
  3. <Environment name="solr/home" type="java.lang.String" value="/soft/solr-cores" override="true"/>  
  4. </Context>  

 此文件爲Solr/home的配置文件

 

 

12.修改tomcat/bin/cataina.sh 文件,在最上方加入    

 JAVA_OPTS="-DzkHost=master:2181,slave1:2181,slave2:2181"                          

 或直接使用ip                                 JAVA_OPTS="-DzkHost=192.168.91.128:2181,192.168.91.129:2181,192.168.91.130:2181"
加入以上內容其實就是指明瞭zookeeper集羣所在位置。


13.將以上配置分別發到其他兩臺機子。

14.SolrCloud是通過ZooKeeper集羣來保證配置文件的變更及時同步到各個節點上,所以,需要將配置文件上傳到ZooKeeper集羣中:執行如下操作(以下ip均可使用域名進行操作)。

 

Java代碼  收藏代碼
  1. java -classpath .:/usr/local/solrcloud/solr-lib/* org.apache.solr.cloud.ZkCLI -cmd upconfig -zkhost 192.168.91.128:2181,192.168.91.129:2181,192.168.91.130:2181 -confdir /usr/local/solrcloud/config-files/ -confname myconf  

 鏈接zookeeper的配置內容:

 

 

Java代碼  收藏代碼
  1. java -classpath .:/usr/local/solrcloud/solr-lib/* org.apache.solr.cloud.ZkCLI -cmd linkconfig -collection collection1 -confname myconf -zkhost 192.168.91.128:2181,192.168.91.129:2181,192.168.91.130:2181  

 

操作如圖:

 

 



 

15.上傳完成以後,我們檢查一下ZooKeeper上的存儲情況:

 

 

Java代碼  收藏代碼
  1. [root@master ~]# cd /soft/zookeeper-3.4.5/bin  
  2. [root@master bin]# ./zkCli.sh -server 192.168.91.128:2181  
  3. ...  
  4. [zk: 192.168.91.128:2181(CONNECTED) 0] ls /  
  5. [configs, collections, zookeeper]  
  6. [zk: 192.168.91.128:2181(CONNECTED) 1] ls /configs  
  7. [myconf]  
  8. [zk: 192.168.91.128:2181(CONNECTED) 2] ls /configs/myconf  
  9. [admin-extra.menu-top.html, currency.xml, protwords.txt, mapping-FoldToASCII.txt, solrconfig.xml, lang, stopwords.txt, spellings.txt, mapping-ISOLatin1Accent.txt, admin-extra.html, xslt, scripts.conf, synonyms.txt, update-script.js, velocity, elevate.xml, admin-extra.menu-bottom.html, schema.xml]  
  10. [zk: 192.168.91.128:2181(CONNECTED) 3]  

 

 

16.啓動tomcat,首先啓動master結點上的tomcat                    
這時候,SolrCloud集羣中只有一個活躍的節點,而且默認生成了一個collection1實例,這個實例實際上虛擬的,因爲通過web界面無法訪問http://192.168.91.128:8080/solr/,看不到任何有關SolrCloud的信息,如圖所示:


17.啓動其他兩個結點上的tomcat

 

18.查看ZooKeeper集羣中數據狀態:


 這時,已經存在3個活躍的節點了,但是SolrCloud集羣並沒有更多信息,
訪問http://192.168.91.128:8080/solr/後,同上面的圖是一樣的,沒有SolrCloud相關數據。

 

19.創建Collection、Shard和Replication

 

創建Collection及初始Shard:


通過REST接口來創建Collection

 

Java代碼  收藏代碼
  1. curl 'http://192.168.91.128:8080/solr/admin/collections?action=CREATE&name=mycollection&numShards=3&replicationFactor=1'  

 上面鏈接中的幾個參數的含義,說明如下:
name          待創建Collection的名稱 
numShards        分片的數量 
replicationFactor   複製副本的數量

 

操作如圖:



 

執行上述操作如果沒有異常,已經創建了一個Collection,名稱爲mycollection,而且每個節點上存在一個分片。這時,也可以查看ZooKeeper中狀態:

 



 

可以通過Web管理頁面,訪問http://192.168.91.128:8080/solr/#/~cloud查看SolrCloud集羣的分片信息,如圖所示:



 由上圖可以看到,對應節點上SOLR分片的對應關係:
shard1     192.168.91.130          slave2
shard2     192.168.91.129          slave1  
shard3     192.168.91.128           master
實際上,我們從master節點可以看到,SOLR的配置文件內容,已經發生了變化,如下所示: 


 我們可以再通過REST接口分別在slave1、slave2結點上創建兩個collection,分別命名爲mycollection1、mycollection2
創建後的訪問鏈接如圖:


創建Replication:


下面對已經創建的初始分片進行復制:
master結點 上的分片shard1已經存在slave2,現在我們複製分片到master和slave1上 
執行操作:

 

Java代碼  收藏代碼
  1. curl 'http://192.168.91.128:8080/solr/admin/cores?action=CREATE&collection=mycollection&name=mycollection_shard1_replica1&shard=shard1'  

 

Java代碼  收藏代碼
  1. curl 'http://192.168.91.129:8080/solr/admin/cores?action=CREATE&collection=mycollection&name=mycollection_shard1_replica2&shard=shard1'  

 操作如圖:

 



 

訪問鏈接查看效果圖:

 



 此時在master結點的slave2的shard1分片上多了兩個副本,名稱分別爲:mycollection_shard1_replica1和mycollection_shard1_replica2
我們再次從master節點可以看到,SOLR的配置文件內容,又發生了變化,如下所示:



 到此爲止,我們基於3個物理節點,配置完成了SolrCloud集羣多結點的配置。

 

 

三、索引操作實例

 

Java代碼  收藏代碼
  1. import java.io.IOException;  
  2. import java.net.MalformedURLException;  
  3. import java.util.ArrayList;  
  4. import java.util.Collection;  
  5. import org.apache.solr.client.solrj.SolrQuery;  
  6. import org.apache.solr.client.solrj.SolrServer;  
  7. import org.apache.solr.client.solrj.SolrServerException;  
  8. import org.apache.solr.client.solrj.impl.CloudSolrServer;  
  9. import org.apache.solr.client.solrj.response.QueryResponse;  
  10. import org.apache.solr.common.SolrDocument;  
  11. import org.apache.solr.common.SolrDocumentList;  
  12. import org.apache.solr.common.SolrInputDocument;  
  13.   
  14. /** 
  15.  * SolrCloud 索引增刪查測試 
  16.  * @author ziyuzhang 
  17.  * 
  18.  */  
  19. public class SolrCloud {        
  20.     private static CloudSolrServer cloudSolrServer;    
  21.         
  22.     private  static synchronized CloudSolrServer getCloudSolrServer(final String zkHost) {    
  23.         if(cloudSolrServer == null) {    
  24.             try {    
  25.                 cloudSolrServer = new CloudSolrServer(zkHost);    
  26.             }catch(MalformedURLException e) {    
  27.                 System.out.println("The URL of zkHost is not correct!! Its form must as below:\n zkHost:port");    
  28.                 e.printStackTrace();    
  29.             }catch(Exception e) {    
  30.                 e.printStackTrace();                    
  31.             }    
  32.         }    
  33.             
  34.         return cloudSolrServer;    
  35.     }    
  36.         
  37.     private void addIndex(SolrServer solrServer) {          
  38.         try {    
  39.             SolrInputDocument doc1 = new SolrInputDocument();    
  40.             doc1.addField("id""421245251215121452521251");    
  41.             doc1.addField("area""北京");    
  42.             SolrInputDocument doc2 = new SolrInputDocument();    
  43.             doc2.addField("id""4224558524254245848524243");    
  44.             doc2.addField("area""上海");    
  45.                 
  46.             SolrInputDocument doc3 = new SolrInputDocument();    
  47.             doc3.addField("id""4543543458643541324153453");    
  48.             doc3.addField("area""重慶");    
  49.                 
  50.             Collection<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();    
  51.             docs.add(doc1);    
  52.             docs.add(doc2);    
  53.             docs.add(doc3);    
  54.       
  55.             solrServer.add(docs);               
  56.             solrServer.commit();    
  57.                 
  58.         }catch(SolrServerException e) {    
  59.             System.out.println("Add docs Exception !!!");    
  60.             e.printStackTrace();            
  61.         }catch(IOException e){    
  62.             e.printStackTrace();    
  63.         }catch (Exception e) {    
  64.             System.out.println("Unknowned Exception!!!!!");    
  65.             e.printStackTrace();    
  66.         }           
  67.             
  68.     }    
  69.         
  70.         
  71.     public void search(SolrServer solrServer, String String) {          
  72.         SolrQuery query = new SolrQuery();    
  73.         query.setQuery(String);    
  74.         try {    
  75.             QueryResponse response = solrServer.query(query);    
  76.             SolrDocumentList docs = response.getResults();    
  77.     
  78.             System.out.println("文檔個數:" + docs.getNumFound());    
  79.             System.out.println("查詢時間:" + response.getQTime());    
  80.     
  81.             for (SolrDocument doc : docs) {    
  82.                 String area = (String) doc.getFieldValue("area");    
  83.                 Long id = (Long) doc.getFieldValue("id");    
  84.                 System.out.println("id: " + id);    
  85.                 System.out.println("area: " + area);    
  86.                 System.out.println();    
  87.             }    
  88.         } catch (SolrServerException e) {    
  89.             e.printStackTrace();    
  90.         } catch(Exception e) {    
  91.             System.out.println("Unknowned Exception!!!!");    
  92.             e.printStackTrace();    
  93.         }    
  94.     }    
  95.         
  96.     public void deleteAllIndex(SolrServer solrServer) {    
  97.         try {    
  98.             solrServer.deleteByQuery("*:*");// delete everything!    
  99.             solrServer.commit();    
  100.         }catch(SolrServerException e){    
  101.             e.printStackTrace();    
  102.         }catch(IOException e) {    
  103.             e.printStackTrace();    
  104.         }catch(Exception e) {    
  105.             System.out.println("Unknowned Exception !!!!");    
  106.             e.printStackTrace();    
  107.         }    
  108.     }    
  109.         
  110.     /**  
  111.      * @param args  
  112.      */    
  113.     public static void main(String[] args) {      
  114.             final String zkHost = "192.168.91.128:2181,192.168.91.129:2181,192.168.91.130:2181";         
  115.             final String  defaultCollection = "mycollection";    
  116.             final int  zkClientTimeout = 20000;    
  117.             final int zkConnectTimeout = 1000;    
  118.                 
  119.             CloudSolrServer cloudSolrServer = getCloudSolrServer(zkHost);           
  120.             System.out.println("The Cloud SolrServer Instance has benn created!");              
  121.             cloudSolrServer.setDefaultCollection(defaultCollection);    
  122.             cloudSolrServer.setZkClientTimeout(zkClientTimeout);    
  123.             cloudSolrServer.setZkConnectTimeout(zkConnectTimeout);                     
  124.             cloudSolrServer.connect();    
  125.             System.out.println("The cloud Server has been connected !!!!");              
  126.             //測試實例!    
  127.             SolrCloud test = new SolrCloud();           
  128.     //        System.out.println("測試添加index!!!");         
  129.             //添加index    
  130.     //        test.addIndex(cloudSolrServer);    
  131.                 
  132.     //        System.out.println("測試查詢query!!!!");    
  133.     //        test.search(cloudSolrServer, "id:*");    
  134.     //            
  135.     //        System.out.println("測試刪除!!!!");    
  136.     //        test.deleteAllIndex(cloudSolrServer);    
  137.     //        System.out.println("刪除所有文檔後的查詢結果:");    
  138.             test.search(cloudSolrServer, "zhan");        
  139.     //        System.out.println("hashCode"+test.hashCode());  
  140.                         
  141.              // release the resource     
  142.             cloudSolrServer.shutdown();    
  143.      
  144.     }    
  145.     
  146. }  

 

 

注:別忘了修改核心配置文件schema.xml,要有id 和 area,注意類型的匹配。


上傳配置文件到ZK裏

/data/hedanhua/solr-5.2.1/server/scripts/cloud-scripts/zkcli.sh -zkhost 192.168.10.156:2181,192.168.10.155:2181,192.168.10.154:2181/solr -cmd upconfig -collection userinfo -confdir /data/hedanhua/solr-5.2.1/server/solr/configsets/data_driven_schema_configs/conf/ -confname userinfo


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章