ZooKeeper 集群組態

雖然 Solr 捆綁了 Apache ZooKeeper,但強烈建議您在生產環境中使用外部 ZooKeeper 設定。

雖然使用 Solr 的內嵌 ZooKeeper 實例對於入門來說很好,但您不應在生產環境中使用它,因為它不提供任何容錯移轉:如果託管 ZooKeeper 的 Solr 實例關閉,ZooKeeper 也會關閉。任何依賴它的分片或 Solr 實例將無法與其或彼此通訊。

此問題的解決方案是設定外部 ZooKeeper集群,這是一些執行 ZooKeeper 的伺服器,它們彼此通訊以協調叢集的活動。

ZooKeeper 節點數量?

要回答的第一個問題是您將在集群中執行的 ZooKeeper 節點數量。

在規劃要設定多少個 ZooKeeper 節點時,請記住 ZooKeeper 集群的主要原則是維護大多數伺服器來服務請求。此大多數稱為法定人數

「為了使 ZooKeeper 服務處於活動狀態,必須有多數可以互相通訊且不會故障的機器。要建立可以容忍 F 台機器故障的部署,您應該考慮部署 2xF+1 台機器。」

— ZooKeeper 管理員指南
https://zookeeper.dev.org.tw/doc/r3.9.2/zookeeperAdmin.html

為了正確維護法定人數,強烈建議您的集群中擁有奇數個 ZooKeeper 伺服器,以便維持多數。

為了解釋原因,請考慮以下情境:如果您有兩個 ZooKeeper 節點,其中一個關閉,這表示只有 50% 的可用伺服器可用。由於這不是多數,ZooKeeper 將不再服務請求。

然而,如果您有三個 ZooKeeper 節點,其中一個節點發生故障,您仍然有 66% 的伺服器可用,並且 ZooKeeper 會在您修復故障節點的同時繼續正常運作。如果您有 5 個節點,必要時可以在兩個節點故障的情況下繼續運作。

一般來說,不建議超過 5 個節點。雖然看起來更多節點可以提供更高的容錯能力和可用性,但實際上,由於節點間協調的次數增加,效率反而會降低。除非您有一個真正龐大的 Solr 叢集(規模達到數千個節點),否則一般來說,盡量保持在 3 個節點,如果您的叢集較大,則可以考慮 5 個節點。

有關 ZooKeeper 叢集的更多資訊,請參閱 ZooKeeper 文件:https://zookeeper.dev.org.tw/doc/r3.9.2/zookeeperAdmin.html#sc_zkMulitServerSetup

下載 Apache ZooKeeper

設定 Apache ZooKeeper 的第一步當然是下載軟體。您可以從 https://zookeeper.dev.org.tw/releases.html 下載。

Solr 目前使用 Apache ZooKeeper v3.9.2。

當使用外部 ZooKeeper 集群時,您需要使您的本地安裝與 Solr 發佈的最新版本保持同步。由於在這種情況下它是一個獨立應用程式,因此它不會作為標準 Solr 升級的一部分進行升級。

ZooKeeper 安裝

安裝包括將檔案解壓縮到您希望 ZooKeeper 儲存其內部資料的特定目標目錄中。實際的目錄本身並不重要,只要您知道它在哪裡即可。

解壓縮 ZooKeeper 套件的指令是

tar xvf zookeeper-3.9.2.tar.gz

此位置是該伺服器上 ZooKeeper 的 <ZOOKEEPER_HOME>

必須在每個將執行 ZooKeeper 的伺服器上重複安裝和解壓縮 ZooKeeper 的步驟。

ZooKeeper 集群的設定

安裝後,我們將首先看看 ZooKeeper 的基本設定,然後是將每個節點設定為集群一部分的特定參數。

初始設定

要設定您的 ZooKeeper 實例,請建立一個名為 <ZOOKEEPER_HOME>/conf/zoo.cfg 的檔案。ZooKeeper 安裝中包含一個範例設定檔,名稱為 conf/zoo_sample.cfg。如果您願意,可以編輯和重新命名該檔案,而不是建立新檔案。

該檔案應包含以下資訊以開始

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
4lw.commands.whitelist=mntr,conf,ruok

參數如下

tickTime

必要

預設值:無

ZooKeeper 的功能之一是判斷哪些伺服器在任何給定時間處於運作狀態,最小會話逾時時間定義為兩個「tick」。tickTime 參數以毫秒為單位指定每個 tick 的持續時間。

dataDir

必要

預設值:無

這是 ZooKeeper 將儲存有關叢集資料的目錄。首次啟動 ZooKeeper 之前,此目錄必須為空。

clientPort

必要

預設值:無

這是 Solr 將存取 ZooKeeper 的連接埠。

4lw.commands.whitelist

選用

預設值:無

這允許 Solr 管理 UI 查詢 ZooKeeper。您可以選擇使用 * 來啟用所有「4 個字母的指令」,列出的三個(mntrconfruok)將啟用管理 UI。

這些是每個 ZooKeeper 節點都需要使用的基本參數,因此必須將此檔案複製到或建立在每個節點上。

接下來,我們將自訂此設定,使其在集群中運作。

集群設定

要完成集群的設定,我們需要設定其他參數,以便每個節點都知道自己在集群中的身分,以及其他每個節點的位置。

以下每個範例都假設您將 ZooKeeper 安裝在具有不同主機名稱的不同伺服器上。

完成後,您的 zoo.cfg 檔案可能如下所示

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
4lw.commands.whitelist=mntr,conf,ruok

initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

autopurge.snapRetainCount=3
autopurge.purgeInterval=1

我們已將這些參數新增到我們已有的三個參數中

initLimit

必要

預設值:無

允許追隨者連線並同步至領導者的時間量(以 tick 為單位)。在這種情況下,您有 5 個 tick,每個 tick 持續 2000 毫秒,因此伺服器將等待長達 10 秒以連線並與領導者同步。

syncLimit

必要

預設值:無

允許追隨者與 ZooKeeper 同步的時間量(以 tick 為單位)。如果追隨者落後領導者太遠,它們將被捨棄。

server.X

必要

預設值:無

這些是集群中所有伺服器的伺服器 ID(X 部分)、主機名稱(或 IP 位址)和連接埠。ID 區分叢集的每個節點,並允許每個節點知道其他每個節點的位置。連接埠可以是您選擇的任何連接埠;ZooKeeper 的預設連接埠是 2888:3888

由於我們已將伺服器 ID 指派給特定主機/連接埠,因此我們還必須定義此節點在清單中是哪個伺服器。我們透過儲存在資料目錄(由 dataDir 參數定義)中的 myid 檔案來完成此操作。myid 檔案的內容只有伺服器 ID。

在上面的設定範例中,您將建立檔案 /var/lib/zookeeper/1/myid,內容為 "1"(不含引號),如本範例所示

1
autopurge.snapRetainCount

選用

預設值:3

在清除舊的快照和交易日誌時要保留的快照和對應交易日誌的數量。

ZooKeeper 會自動保留交易日誌,並在進行變更時將變更寫入其中。會定期建立目前狀態的快照,而此快照會取代早於該快照的交易日誌。但是,ZooKeeper 永遠不會清除舊的快照或舊的交易日誌;隨著時間推移,它們會在每個伺服器上靜默地填滿可用的磁碟空間。

為了避免這種情況,請設定 autopurge.snapRetainCountautopurge.purgeInterval 參數,以啟用定期自動清除 (purge)。autopurge.snapRetainCount 參數會在清除發生時保留定義數量的快照和交易日誌。此參數可以設定高於 3,但不能設定低於 3。

autopurge.purgeInterval

選用

預設值:0

清除任務之間的時間(以小時為單位)。此參數的預設值為 0,因此必須設定為 1 或更高,才能啟用自動清除快照和交易日誌。如果首選,設定為高達 24(每天一次)是可以接受的。

我們將在每個節點上重複此設定。

在第二個節點上,更新 <ZOOKEEPER_HOME>/conf/zoo.cfg 檔案,使其符合節點 1 上的內容(特別是伺服器主機和連接埠)

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
4lw.commands.whitelist=mntr,conf,ruok

initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

autopurge.snapRetainCount=3
autopurge.purgeInterval=1

在第二個節點上,建立一個內容為 "2" 的 myid 檔案,並將其放在 /var/lib/zookeeper 目錄中。

2

在第三個節點上,更新 <ZOOKEEPER_HOME>/conf/zoo.cfg 檔案,使其符合節點 1 和 2 上的內容(特別是伺服器主機和連接埠)

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
4lw.commands.whitelist=mntr,conf,ruok

initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

autopurge.snapRetainCount=3
autopurge.purgeInterval=1

並在 /var/lib/zookeeper 目錄中建立 myid 檔案

3

如果您正在建立 5 個節點的集群(一種罕見的情況),請對伺服器 4 和 5 重複此操作。

ZooKeeper 環境設定

為了在稍後出現叢集問題時方便進行疑難排解,建議啟用記錄功能並使用適當的 JVM 垃圾收集 (GC) 設定來執行 ZooKeeper。

  1. 建立一個名為 zookeeper-env.sh 的檔案,並將其放在 <ZOOKEEPER_HOME>/conf 目錄中(您放置 zoo.cfg 的相同位置)。此檔案需要存在於叢集的每個伺服器上。

  2. 將以下設定新增到檔案中

    ZOO_LOG_DIR="/path/for/log/files"
    ZOO_LOG4J_PROP="INFO,ROLLINGFILE"
    
    SERVER_JVMFLAGS="-Xms2048m -Xmx2048m -Xlog:gc*:file=$ZOO_LOG_DIR/zookeeper_gc.log:time,uptime:filecount=9,filesize=20M"

    ZOO_LOG_DIR 屬性定義伺服器上 ZooKeeper 將列印其記錄的位置。ZOO_LOG4J_PROP 設定記錄層級和記錄附加程式。

    透過 SERVER_JVMFLAGS,我們定義了垃圾收集和記錄 GC 相關事件的幾個參數。其中一個系統參數是 -Xloggc:$ZOO_LOG_DIR/zookeeper_gc.log,它會將垃圾收集記錄放在我們為 ZooKeeper 記錄定義的相同目錄中,在一個名為 zookeeper_gc.log 的檔案中。

  3. 檢閱 <ZOOKEEPER_HOME>/conf/log4j.properties 中的預設設定,特別是 log4j.appender.ROLLINGFILE.MaxFileSize 參數。這設定記錄檔案將被輪換的大小,預設為 10MB。

  4. zookeeper-env.sh 以及對 log4j.properties 所做的任何變更複製到叢集中的每個伺服器。

上述說明僅適用於 Linux 伺服器。預設的 zkServer.sh 指令碼包含對 zookeeper-env.sh 檔案的支援,但是 Windows 版本的指令碼 zkServer.cmd 不包含。若要在 Windows 伺服器上進行相同的設定,則需要直接在 zkServer.cmd 中進行變更。

此時,您已準備好啟動您的 ZooKeeper 集群。

有關 ZooKeeper 的更多資訊

ZooKeeper 透過其他設定提供了強大的功能,但是深入研究它們超出了 Solr 文件涵蓋的範圍。如需更多資訊,請參閱 ZooKeeper 文件

啟動和停止 ZooKeeper

啟動 ZooKeeper

若要啟動叢集,請使用 <ZOOKEEPER_HOME>/bin/zkServer.shzkServer.cmd 指令碼,如下列指令所示

Linux 作業系統
zkServer.sh start
Windows 作業系統
zkServer.cmd start

需要在每個將執行 ZooKeeper 的伺服器上執行此指令。

您應該會在您定義儲存位置的目錄中看到 ZooKeeper 記錄。但是,在啟動後,您可能不會立即看到 zookeeper_gc.log,因為它可能要等到垃圾收集首次發生後才會出現。

關閉 ZooKeeper

若要關閉 ZooKeeper,請在每個伺服器上使用相同的 zkServer.shzkServer.cmd 指令碼,並使用 "stop" 指令

Linux 作業系統
zkServer.sh stop
Windows 作業系統
zkServer.cmd stop

Solr 設定

啟動 Solr 時,您必須提供 ZooKeeper 的位址,否則 Solr 將不知道如何使用它。這可以透過兩種方式完成:在 Solr 叢集的每個節點上,每次啟動時定義 * 連接字串 *(ZooKeeper 執行所在的伺服器清單),或將 Solr 的包含檔案編輯為永久的系統參數。以下說明這兩種方法。

在 Solr 中參考 ZooKeeper 的位置時,最好使用叢集中所有伺服器的位址。如果其中一個伺服器發生故障,Solr 將自動能夠將其請求傳送到清單中的另一個伺服器。

ZooKeeper 3.5 版及更高版本支援動態重新配置伺服器位址和角色。但請注意,Solr 將只能與靜態 ZooKeeper 連接字串中列出的伺服器進行通訊。

使用 chroot

如果您的叢集(ensemble)是或將會與 Solr 以外的其他系統共享,您應該考慮定義特定於應用程式的znodes,或一個僅包含 Solr 檔案的階層式命名空間。

一旦您為每個應用程式建立了一個 znode,您就需要將它的名稱(也稱為 chroot)加到您的連接字串末尾,無論何時您告訴 Solr 存取 ZooKeeper。

建立 chroot 是使用 bin/solr 指令完成的。

bin/solr zk mkroot /solr -z zk1:2181,zk2:2181,zk3:2181

請參閱建立一個 znode章節,以取得此指令的更多範例。

一旦建立 znode,它的行為方式與檔案系統上的目錄類似:Solr 儲存在 ZooKeeper 中的資料會巢狀在主資料目錄下,不會與使用相同 ZooKeeper 叢集的另一個系統或程序的資料混合。

或者,Solr 可以自動建立 znode 作為第一個 Solr 實例啟動的一部分,請閱讀以下範例。

使用 bin/solr 的 -z 參數

將 Solr 指向您建立的 ZooKeeper 叢集,只需在使用 bin/solr 腳本時使用 -z 參數即可。

例如,要將 Solr 實例指向您在三個伺服器上,埠號 2181 上啟動的 ZooKeeper,且 chroot 為 /solr(請參閱上面的使用 chroot),您需要這樣做:

bin/solr start -e cloud -z zk1:2181,zk2:2181,zk3:2181/solr

如果 znode 不存在,您可以將 ZK_CREATE_CHROOT 環境變數設定為 true,以在啟動時自動建立它。

ZK_CREATE_CHROOT=true bin/solr start -e cloud -z zk1:2181,zk2:2181,zk3:2181/solr

更新 Solr 包含檔案

如果您更新 Solr 包含檔案(solr.in.shsolr.in.cmd),這些檔案會覆蓋 bin/solr 使用的預設值,您就不必在 bin/solr 指令中使用 -z 參數。

  • Linux

  • Windows

solr.in.sh

要尋找的部分將被註解掉。

# Set the ZooKeeper connection string if using an external ZooKeeper ensemble
# e.g. host1:2181,host2:2181/chroot
# Leave empty if not using SolrCloud
#ZK_HOST=""

移除行首的註解符號,並輸入 ZooKeeper 連接字串。

# Set the ZooKeeper connection string if using an external ZooKeeper ensemble
# e.g. host1:2181,host2:2181/chroot
# Leave empty if not using SolrCloud
ZK_HOST="zk1:2181,zk2:2181,zk3:2181/solr"
solr.in.cmd

要尋找的部分將被註解掉。

REM Set the ZooKeeper connection string if using an external ZooKeeper ensemble
REM e.g. host1:2181,host2:2181/chroot
REM Leave empty if not using SolrCloud
REM set ZK_HOST=

移除行首的註解符號,並輸入 ZooKeeper 連接字串。

REM Set the ZooKeeper connection string if using an external ZooKeeper ensemble
REM e.g. host1:2181,host2:2181/chroot
REM Leave empty if not using SolrCloud
set ZK_HOST=zk1:2181,zk2:2181,zk3:2181/solr

現在您在啟動 Solr 時就不必輸入連接字串了。

增加檔案大小限制

ZooKeeper 設計用於保存小型檔案,大約在 KB 等級。預設情況下,ZooKeeper 的檔案大小限制為 1MB。嘗試寫入或讀取大於此限制的檔案將會導致錯誤。

某些 Solr 功能,例如文字分析同義詞、LTR 和 OpenNLP 命名實體辨識,需要可能大於預設限制的配置資源。可以通過 Java 系統屬性 jute.maxbuffer 配置 ZooKeeper 來增加此限制。請注意,此配置對於 ZooKeeper 伺服器以及所有連接到伺服器的客戶端都是必需的,並且在指定它的任何地方都必須相同。

在 ZooKeeper 節點上配置 jute.maxbuffer

必須在每個外部 ZooKeeper 節點上配置 jute.maxbuffer。這可以通過以下任何一種方式實現;但請注意,只有第一種方式在 Windows 上有效。

  1. <ZOOKEEPER_HOME>/conf/zoo.cfg 中,例如,將檔案大小限制增加到小於 10MB 的一個位元組,請新增以下這行:

    jute.maxbuffer=0x9fffff
  2. <ZOOKEEPER_HOME>/conf/zookeeper-env.sh 中,例如,將檔案大小限制增加到 50MiB,請新增以下這行:

    JVMFLAGS="$JVMFLAGS -Djute.maxbuffer=50000000"
  3. <ZOOKEEPER_HOME>/bin/zkServer.sh 中,在腳本頂部附近新增一個 JVMFLAGS 環境變數賦值,例如,將檔案大小限制增加到 5MiB:

    JVMFLAGS="$JVMFLAGS -Djute.maxbuffer=5000000"

為 ZooKeeper 客戶端配置 jute.maxbuffer

bin/solr 腳本會調用充當 ZooKeeper 客戶端的 Java 程式。當您使用 Solr 捆綁的 ZooKeeper 伺服器而不是設定外部 ZooKeeper 叢集時,下面描述的配置也將配置 ZooKeeper 伺服器。

將設定新增到 Solr 包含檔案(bin/solr.in.shsolr.in.cmd)中的 SOLR_OPTS 環境變數中。

  • Linux

  • Windows

solr.in.sh

要尋找的部分將會從這裡開始:

# Anything you add to the SOLR_OPTS variable will be included in the java
# start command line as-is, in ADDITION to other options. If you specify the
# -a option on start script, those options will be appended as well. Examples:

新增以下這行,將檔案大小限制增加到 2MB:

SOLR_OPTS="$SOLR_OPTS -Djute.maxbuffer=0x200000"
solr.in.cmd

要尋找的部分將會從這裡開始:

REM Anything you add to the SOLR_OPTS variable will be included in the java
REM start command line as-is, in ADDITION to other options. If you specify the
REM -a option on start script, those options will be appended as well. Examples:

新增以下這行,將檔案大小限制增加到 2MB:

set SOLR_OPTS=%SOLR_OPTS% -Djute.maxbuffer=0x200000

保護 ZooKeeper 連接

您可能還希望保護 ZooKeeper 和 Solr 之間的通信安全。

要設定 znodes 的 ACL 保護,請參閱 ZooKeeper 存取控制章節。