一、前言
平台:CDH 5.13.0
公司在客戶那邊有個項目需要部署cloudera平台,部署的時候,在這個版本的cdh中,除了基本組件,還選了sqoop2作為數據傳輸工具,希望能在Oozie中通過工作流調用sqoop。
二、問題與解決
1. hue界面找不到sqoop2的action
如下圖所示,無論在Editor還是在workflow的操作界面,只有sqoop1的操作,沒有sqoop2的。
然后在博客中找到了原因:
Oozie 自帶 sqoop、hive 等常用組件,比如執行sqoop腳本命令時,並不是你主機里或者CDH里的的sqoop,而是 HDFS 下 Oozie 里的 sqoop 在起作用,這也是為什么 總是報 Could not load db driver class 的原因了,因為根本不是同一個sqoop。[1]
也搜索到了sqoop1和sqoop2的區別:https://blog.csdn.net/Gamer_gyt/article/details/55225700
然而我們只需要簡單的工具,能夠從關系型數據庫中導入數據而已,所以思路轉為調用sqoop1進行數據導入。
2. 無法導入db驅動的類
“Could not load db driver class”,這句估計是出現次數最多的報錯了,這個報錯搞了一天,所以要一步步來(以下操作在安裝oozie的主機進行操作):
我的需求是從sqlserver導入數據,所以需要從微軟的官網下載驅動:https://docs.microsoft.com/en-us/sql/connect/jdbc/download-microsoft-jdbc-driver-for-sql-server?view=sql-server-2017 ,我選擇是6.0的版本,解壓后,獲得sqljdbc42.jar
3. 本地執行sqoop命令
將sqljdbc42.jar放入/var/lib/sqoop/目錄,然后將用戶和組改為sqoop。
ssh登錄主機,我是用root執行命令:
sqoop import --connect 'jdbc:sqlserver://{IP}:{Port};username={UserName};password={Paswd};database={Dbname}' --table table_name --target-dir "/user/root/sqoop_dir" -m 1
如果能夠正常執行,並且在hdfs上發現/user/root/sqoop_dir 目錄中有正確的數據,證明sqoop命令和驅動都是正常的。
4. 通過sqoop action方式運行
首先,將sqljdbc42.jar包,復制到hdfs中的目錄:/user/oozie/share/lib/lib_{timestamp}/sqoop/ 其中timestamp因人而異;
可以通過命令:
oozie admin -oozie http://{Ip}:11000/oozie –sharelibupdate
更新共享庫,可以看到你現在oozie的共享庫是哪個。
然后,將jar包的owner和group都改成oozie;
最后,在cloudera界面重啟oozie組件;
做完這些之后,新建一個workflow,如下圖所示:
編輯內容填入sqoop語句,注意,網上有人說這里不能帶sqoop命令了,也就是直接以import開頭,但是我執行之后,發現用完整的命令是可以執行的。
有個坑是,剛開始字符串用單引號,會報錯,改成雙引號后就可以運行了,執行結果如下:
但是,使用sqoop action執行數據導入會有一個致命的問題,就是無法使用—query “sql語句”的方式去動態的選擇數據,原因是oozie在解析command的時候,會將空格當作分隔符進行分割,所以會報無法識別參數的錯,這個通過查看workflow.xml可以看出oozie轉化后的文件,詳情可以看:Oozie – Sqoop Job Failed When Executing It With Hue。
5. 通過shell action方式運行
由於oozie的bug,導致無法使用sqoop action進行操作,所以還是需要將sqoop命令寫入shell腳本,利用shell action去執行。
但是無論我把驅動包拷貝入oozie server所在主機還是namenode所在主機的相關目錄,還是會報找不到驅動,最后沒辦法,把驅動包分發到各個節點的/var/lib/sqoop目錄,竟然就成功了!
接下來的問題就是權限問題,因為shell script默認是使用yarn用戶進行執行任務,需要你在shell前面指定執行用戶:
export HADOOP_USER_NAME=username
接下來就可以順利將sqlserver的數據導入到hdfs中了。
最后我做了一個實驗,分別刪除datanode節點上的驅動,發現一個規律:
workflow會隨機在一個節點對sqoop命令進行調用。
我猜想,應該取決於yarn將MapReduce任務分配到哪部主機上執行。我覺得應該有參數可以設置從哪里讀取驅動的,希望有辦法的朋友不吝留下您的解決方法。
三、參考
(完)