HiveServer2的ActivePassive高可用與常見高可用淺析


負載均衡的高可用

最近在工作中遇到了hiveserver2需要部署高可用的場景,去網上搜索了解過后,用了絕大多數人推薦的共同方法:

Property_name Property_value Description
hive.server2.support.dynamic.service.discovery true(默認false) 使hiveserver2服務可被動態發現
hive.server2.zookeeper.namespace hiveserver2(默認值) hiveserver2實例在zk中注冊的znode名
hive.zookeeper.client.port 2181(默認值) zk端口
hive.zookeeper.quorum zk1:2181,zk2:2181,zk3:2181(默認空) zk集群連接方式

當如上配置后,啟動的hiveserver2實例都會注冊到zk的/hiveserver2節點下,如下所示
注冊的hs2實例

get一下其中一個實例,就會發現它包含了這個hs2的uri、端口號等連接配置,如下所示
每一個實例具體包含的信息

此時用客戶端(如beeline)連接hs2時,url需使用
jdbc:hive2://zk1:2181,zk2:2181,zk3:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2
此時zk會隨機從多個實例中隨機拿一個實例供連接使用,過程在代碼中體現如下:

連接hs2實例過程

先去指定的znode(/hiveserver2)下拿到所有實例,再通過Random隨機拿其中一個去連接;也正因為這個隨機的過程,此種方式的hs2高可用一定程度上實現了hiveserver2的負載均衡

問題

但這種方式的高可用在使用中存在一個問題,即當你同時開啟了鑒權的服務(如ranger),hs2在啟動時不僅會注冊hs2的實例,還會注冊一個leader節點,如下所示

注冊的leader節點

從圖中可以看出,leader節點下有兩個子節點,而每個子節點實際沒有任何內容,因為這個leader節點在此處沒有用處。

但因為leader節點的存在,使上面講的隨機拿的過程中就可能會拿到這個leader節點,而該節點實際不是有效的hs2實例,故此時連接會報錯“Unable to read HiveServer2 configs from ZooKeeper”.

那么Leader節點為什么會產生呢?我們看下源碼里對應的部分

leader注冊

而目前還沒有發現leader節點的具體作用,只會在從zk拿實例時徒增報錯。

為了解決此問題,我重新編譯了hive-jdbc的源碼,在從zk拿實例的過程中過濾掉了leader節點。
能解決此問題的,還有另一種方式,即配置ActivePassiveHA。

ActivePassiveHA

探究源碼過程中,發現hive還提供了另一種高可用方案,即ActivePassiveHA,開啟需如下配置:

Property_name Property_value Description
hive.server2.support.dynamic.service.discovery true(默認false) 使hiveserver2服務可被動態發現
hive.server2.active.passive.ha.enable true(默認false) ActivePassiveHA啟用
hive.server2.active.passive.ha.registry.namespace hs2ActivePassiveHA(默認值) hiveserver2實例及leader在zk中注冊的znode名
hive.zookeeper.quorum zk1:2181,zk2:2181,zk3:2181(默認空) zk集群連接方式
hive.zookeeper.client.port 2181(默認值) zk端口

當如上配置后,啟動的hiveserver2實例都會注冊到zk的/hs2ActivePassiveHA節點下,如下所示

節點內容

由圖可見,其本質還是和上面類似的注冊實例的過程相似,但注冊的實例統一放在了instances下面,且注冊時信息更詳細;而單獨產生的_LEADER節點則將兩個實例中的registry.unique.id拿出單獨放置。(hs2ActivePassiveHA后的unsecure或secure是根據是否開啟身份驗證或鑒權后自動添加的)

而ActivePassiveHA和上述高可用方案最大的區別,就是通過_LEADER節點分配可連接實例中的"leader"和"worker",當leader沒有掛掉的時候,所有通過zk連接到hs2的連接都會指向leader節點,而不會連接到其他節點,與上述高可用方案的隨機方式有一定區別。
此時,連接的url需使用
jdbc:hive2://zk1:2181,zk2:2181,zk3:2181/;serviceDiscoveryMode=zooKeeperHA;zooKeeperNamespace=hs2ActivePassiveHA

這種高可用方案同時解決了另一個問題:java.lang.NoClassDefFoundError: org/apache/tez/dag/api/TezConfiguration,如下所示
TezSessionError

這問題出現在hs2啟動過程中,因為對hive3來說mr引擎已經是過時的,所以無論你的hive執行引擎選的是什么,都會在啟動hs2時自動啟動一個TezSession,但如果你在hive-env.sh中沒有配置tez包的位置,這里就會報ClassNotFound,並且強制等待60s后重試,重試后不管成功還是失敗都會繼續向下執行,不影響正常啟動,但拖慢了hs2啟動的時間。本來十幾秒就能解決的事非要等待一分多鍾才行。

但當開啟了ActicePassiveHA后,這個啟動TezSession的過程就會變成此處暫不啟動,后續由leader自行啟動,代碼如下:

HiveServer2.start

問題

此種高可用方案在hive官網和網絡上的帖子中幾乎沒有被提及,是在hs2啟動時跟源碼發現的,目前發現存在一些問題:

  1. 此種方式的高可用在leader節點沒有掛掉的情況下會始終連接leader節點,只有在leader不可用時才會自動切換,類似hadoop的Actice/Standby方案,但這樣只能做到故障切換,沒有做到負載均衡(這種方式在代碼中是否有另外一套負載均衡的機制還有待探究)
  2. url中serviceDiscoveryMode=zooKeeperHA的連接方式不被一些鑒權服務所支持(如ranger)

本文首發於博客園,作者榆天紫夏,希望對大家有所幫助。如有遺漏或問題歡迎補充指正


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM