自從成為架構師()之後,李大胖的學習動力似乎少了一些,尤其是今年(當然也有一些客觀因素)。 臨近歲末,內心著實有些慚愧,決定學習一把大數據。跟隨一下業界前沿(其實已經不是前沿了),夢想著有一天能夠擁有擁有夢想的權力。 操練起來 啟動裝有CentOS的虛擬機(IP是172.18.232.181),按照 ...
自從成為架構師()之後,李大胖的學習動力似乎少了一些,尤其是今年(當然也有一些客觀因素)。
臨近歲末,內心著實有些慚愧,決定學習一把大數據。跟隨一下業界前沿(其實已經不是前沿了),夢想著有一天能夠擁有擁有夢想的權力。
操練起來
啟動裝有CentOS的虛擬機(IP是172.18.232.181),按照官方文檔內容選擇hadoop-2.8.5和hbase-2.0.2,還有zookeeper-3.4.11進行下載、解壓。
以下是官方文檔的步驟,熟悉的同學可以直接跳到“噩夢開始”()。
HDFS
進入hadoop的解壓目錄,進入etc/hadoop/hadoop-env.sh中設置Java目錄,如圖
執行./sbin/start-dfs.sh腳本,如圖
jps一下,發現啟動好了,如圖
執行./bin/hdfs dfs -ls /命令,進到hdfs里看看,如圖
註:初次進來是空的,沒有這個hbase目錄的。
Zookeeper
進入zookeeper解壓目錄,進入conf/zoo.cfg中設置下數據目錄,如圖
執行./bin/zkServer.sh start命令啟動,如圖
jps一下,發現啟動好了,如圖
Hbase
進入hbase的解壓目錄,進入conf/hbase-env.sh中設置Java目錄,如圖
進入conf/hbase-site.xml中修改內容,如圖
註:指定好hdfs,zookeeper和集群模式。
執行./bin/start-hbase.sh腳本啟動,如圖
jps一下,啟動好了,如圖
執行./bin/hbase shell命令,進入shell交互,如圖
可以進行建表,插入數據,刪除數據等(這裡不再演示了)。
最後進入hdfs看一下,發現hbase已經在裡面存了數據,如圖
李大胖發現按照官方文檔一路走下來,非常順暢,心裡不由得成就感倍增(是不是略有膚淺)。
噩夢開始
作為一個寫了近十年Java的老碼農,不用Java連一下Hbase,那怎麼能讓李大胖死心呢(噩夢的種子就在此刻埋進了土裡)。
開始整起來,先弄個springboot,再引入相關依賴、獲取連接等等(具體細節等明年會推文,明年?沒毛病啊),按照官方文檔方法搞好了。
激動的心,顫抖的手,點了運行按鈕。咦,竟然沒報錯,正常啟動了()。
李大胖心想,見證奇跡的時刻到了。就點了頁面上的調用按鈕,仿佛整個世界都在靜靜的等待看到結果的喜悅()。1秒,2秒,3秒過去了,沒反應,不好,估計出問題了,趕緊看下Eclipse的控制台,果然報錯了(噩夢的種子已經發芽了)。錯誤如下:
Caused by: org.apache.hadoop.hbase.MasterNotRunningException: java.net.ConnectException: Call to localhost/127.0.0.1:16000 failed on connection exception: org.apache.hbase.thirdparty.io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: localhost/127.0.0.1:16000
錯誤是說Master沒有運行,原因是訪問localhost/127.0.0.1:16000被拒絕。
得虧學了一點Hbase,知道16000是master(節點)的預設埠(老版本中master的預設埠是60000),只是這個IP為啥是本機啊,李大胖心中有些疑惑,Hbase明明是在虛擬機里運行的呀。
“狄仁傑”辦案
這就像狄仁傑遇到了大案,而且是離奇的案子。此時狄閣老總是說,在大案面前一定要穩住,不能自亂方寸。特別是案件前期撲朔迷離,陷入僵局,你甚至都不知道對手是誰的時候,一定是你在辦案過程中忽略了某些細節,此時你需要從頭仔細回憶一遍,看能不能想起一些蛛絲馬跡(是不是有點入戲太深了)。
好吧,那就跟著李大胖復盤一下吧()。Hbase在啟動的時候會把一些信息註冊到zookeeper中,我們在Java程式中只配置了zookeeper的地址,所以程式是從zookeeper中讀出了master的地址,然後才去訪問的。
既然最後訪問的是localhost/127.0.0.1:16000,說明master註冊的就是它。想到Dubbo在往zookeeper里註冊url時使用的就是IP,所以李大胖認為master往zookeeper里註冊的也是IP,即127.0.0.1:16000。
為了驗證自己的想法,就進到zookeeper里去看,發現有master節點,但是並沒有它的地址信息。既然驗證不了,那就解決問題吧,目前看起來只需要master採用所在機器的實際IP註冊就行了。
於是使用中文關鍵詞進行了搜索,發現可以在hbase-site.xml配置文件中設置一個hbase.master的參數,趕緊加進去試試,如圖:
重啟Hbase後發現不行()。
“元芳”的猜想
李大胖繼續想,這是搭建的偽集群,官方文檔明確說明,偽集群的意思是雖然有多個進程,但是還都是在一個機器上的。會不會是Hbase在啟動時檢測到了自己是偽集群,所以總是用127.0.0.1去註冊啊(請允許李大胖自顧自的胡思亂想)。
俗話說的好,是騾子是馬拉出來遛遛()。首先把zookeeper移到另一臺虛擬機上,重啟Hbase,發現還不行()。莫非還要把HDFS也移到第三台虛擬機上?仔細想想,不對吧,Hbase應該不會自己去檢測安裝方式,單節點/偽集群/真集群,它不會這麼無聊的()。於是放棄了後續的驗證。
李大胖接著想,既然在Hbase的配置文件中可以指定hbase.master配置項,那我直接把這個配置項放到Java程式里試試(),興許管用。但前提是在本機可以訪問虛擬機里的master。
於是進入cmd視窗,執行telnet 172.18.232.181 16000,我去,竟然不通()。趕緊跑到虛擬機里執行telnet 172.18.232.181 16000,我嘞個去,竟然還不通()。既然已經在虛擬機里了,就試試telnet 127.0.0.1 16000,擦,竟然它是通的()。於是忽然想起之前看master日誌時,總是發現綁定到127.0.0.1,只不過當時沒有引起重視。如圖
雪上加霜
得,老的問題還沒解決,新的問題又出現了。那就解決新問題吧,再次使用中文關鍵詞一通搜索,沒有很好的答案。
突然想到,要不使用英文關鍵詞試試,哈哈,一下子就被我get到了。發現這是一個2010年()的提問。八年後被我趕上了,在此非常感謝這個問題的提出者和回答者(https://grokbase.com/t/hbase/user/103pq6p14k/master-binds-only-to-loopback)。
回答中指出,Hbase master綁定的一般演算法是這樣的,分三步(和把大象裝進冰箱里一樣):
1、獲取host name(在posix系統上一般使用hostname命令獲取)
2、在這個hostname上執行DNS查找
3、使用找到的IP作為綁定的IP
忽然想起幾年前看視頻學習時,提到過Java程式部署到Linux後,很多網路問題有時都和hostname有關。
趕緊執行hostname命令,發現結果是localhost,根據localhost得到的IP就是127.0.0.1,所以master最後綁定到了127.0.0.1:16000上。
於是修改了hostname為host1,同時在/etc/hosts文件中將host1映射為本機實際IP,如圖:
重啟Hbase,看master日誌,終於綁定的IP變了,如圖:
我開心地認為是不是所有問題都解決了,趕緊使用Java再調一下,發現還是一開始的錯誤。因為我每次重啟Hbase時都會把logs目錄清空,當我修改完hostname後重啟時,我發現zookeeper的日誌文件名稱發生了變化,原來是以localhost結尾,現在變成以新的hostname結尾了,如圖:
但是發現master的日誌文件還是以localhost結尾,心想是不是因為修改完hostname沒有reboot呀(我既在文件中修改了,又用hostname命令修改了,就是懶得重啟了),算了,還是重啟下吧()。重啟完Linux後,再啟動Hbase,果然master的日誌文件名稱變了,也以host1結尾了,如圖:
又興奮起來了,趕緊再用Java調一下試試,可惜,還是原來的配方,原來的味道()。
痛定思痛
再總結下目前的情況,master在啟動時,已經綁定到正確的IP和埠,即172.18.232.181:16000。但是Java調用時依然是原來的錯誤,即訪問127.0.0.10:16000被拒絕。說明master雖然啟動時server socket綁定對了,但是往zookeeper里註冊時錯了,依然使用的是127.0.0.1:16000()。
此時李大胖更迦納悶,既然綁定都對了,沒有理由往zookeeper里註冊時不對啊。為什麼非要註冊127.0.0.1,而不是實際的IP呢。這個問題之前已經使用中文關鍵詞搜索了很多次,沒有得到解決。
狄公曾經說過,有些案子,錶面上看去是什麼樣子,實際就是什麼樣子。有些案子卻恰恰相反,因為有人在故意矇蔽你的雙眼(也有可能是自我矇蔽了雙眼)。
那這個問題該如何解決呢?或者更準確的說,現在的問題根本還沒有被定位出來,我們看到的錯誤只是一個結果(或者說現象)。
愛因斯坦
愛因斯坦曾經說過,“提出一個問題比解決一個問題更重要”。他還說過,“想象力比知識更重要”。(他的名言翻譯成中國話,怎麼感覺像“沒有做不到的,只有想不到的”。)
正在李大胖一籌莫展時,一道靈光乍現()。等等,既然server socket綁定時是根據hostname找到IP的,而且修改了hostname後連日誌文件名的後面部分都變了,說明和hostname有莫大的關係,且又回憶起master日誌文件中在master註冊時