大家好,3y啊。好些天沒更新了,並沒有偷懶,只不過一直在安裝環境,差點都想放棄了。
上一次比較大的更新是做了austin的預覽地址,把企業微信的應用和機器人訊息各種的訊息型別和功能給完善了。上一篇文章也提到了,austin常規的功能已經更新得差不多了,剩下的就是各種細節的完善。
不知道大家還記不記得我當時規劃austin時,所畫出的架構圖:
現在就剩下austin-datahouse
這個模組沒有實現了,也有挺多同學在看程式碼的時候問過我這個模組在哪...其實就是還沒實現,先規劃,牛逼先吹出去(網際網路人必備技能)
訊息推送平臺?推送下發【郵件】【簡訊】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。
至於這個模組吧,我預想它的功能就是把austin相關的實時資料寫到資料倉儲裡。一方面是做資料備份,另一方面是大多數的報表很多都得依賴資料倉儲去做。實際上,生產環境也會把相關的資料寫到數倉中。
而在公司裡,要把資料寫到資料倉儲,這事對開發來說一般很簡單。因為有數倉這個東西,那大多數都會有相關的基礎建設了。對於開發而言,可能就是把日誌資料寫到Kafka,在相關的後臺配置下這個topic,就能將這個topic的資料同步到資料倉儲裡咯。如果是資料庫的話,那應該大資料平臺有同步資料的功能,對普通開發來說也就配置下表名就能同步到資料倉儲裡咯。
反正使用起來很簡單就是了。不過,我其實不知道具體是怎麼做的。
但是不要緊啊,反正開源專案對於時間這塊還是很充裕得啊:沒有deadline
,沒有產品在隔壁催我寫,沒有相關的技術要跟我對接。那我不懂可以學,於是也花了幾天看了下數倉這塊內容。
在看數倉的同時,我之前在公司經常會聽到資料湖這個詞。我剛畢業的時候是沒聽過的,但這幾年好像這個概念就火起來了。跟大資料那邊聊點事的時候,經常會聽到:資料入湖。
那既然看都看了,順便了解資料湖是個什麼東西吧?對著瀏覽器一輪檢索之後,我發現這個詞還是挺抽象的,一直沒找到讓我耳目一新的答案,這個資料湖也不知道怎麼就火起來了。我瀏覽了一遍之後,我大概可以總結出什麼是資料湖,跟資料倉儲有啥區別:
1、資料倉儲是儲存結構化的資料,而資料湖是什麼資料都能存(非結構化的資料也能存)。結構化資料可以理解為我們的二維表、JSON資料,非結構化的資料可以理解為影像檔案之類的。
資料倉儲在寫入的時候,就要定義好schema了,而資料湖在寫入的時候不需要定schema,可以等用到的時候再查出來。強調這點,說明資料湖對資料的schema約束更加靈活。
2、資料倉儲和資料湖並不是替代關係。資料是先進資料湖,將資料加工(ETL)之後,一部分資料會到資料倉儲中。
3、我們知道現有的資料倉儲一般基於Hadoop體系的HDFS分散式檔案系統去搭建的,而資料湖也得儲存資料的嘛,一般也是依賴HDFS。
4、開源的資料湖技術比較出名的有hudi、iceberg、Delta Lake
看完上面的描述,是不是覺得有點空泛。看似學到了很多,但是實際還是不知道資料湖有啥牛逼之處。嗯,我也是這麼想的。總體下來,感覺資料湖就相當於資料倉儲的ODS,圍繞著這些資料定義了對應的meta資訊,做後設資料的管理。
說到ODS這個詞了,就簡單聊下資料倉儲的分層結構吧。這個行業通用的,一般分為以下:
1、ODS(Operate Data Store),原始資料層,未經過任何加工的。
2、DIM(Dictionary Data Layer),維度資料層,比如儲存地域、使用者客戶端這些維度的資料。
3、DWD(Data Warehouse Detail),資料明細層,把原始資料經過簡單的加工(去除髒資料,空資料之後就得到明細資料)。
4、DWS(Data Warehouse Service),資料維度彙總層,比如將資料明細根據使用者維度做彙總得到的彙總之後的資料。
5、ADS(Application Data Store),資料應用層,這部分資料能給到後端以介面的方式給到前端做視覺化使用了。
至於為什麼要分層,跟當初我們理解DAO/Service/Controller的思想差不多,大概就是複用和便於後續修改變動。
扯了那麼多吧,聊會ausitn專案吧,我是打算怎麼做的呢?因為我的實時計算austin-stream
模組是採用Flink去做的,我打算austin-datahouse
也是採用flink
去做。
這幾年在大資料領域湖倉一體、流批一體這些概念都非常火,而對於austin來說,第一版迭代還不用走得這麼急。我目前的想法是利用flink
的tableapi去對接Hive
,透過Superset
、Metabase
、DataEase
其中一個開源的大資料視覺化工具把Hive
的資料給讀取出來,那第一版就差不多完成了。
現狀
自從我決定開始寫austin-data-house
資料倉儲模組,已經過了兩週有多了。這兩週多我都在被部署安裝環境折磨,中途有很多次就想放棄了。
我初學程式設計,到現在工作了幾年,我還是沒變,一如既往地討厭安裝環境。
花了這麼長時間除錯安裝部署環境,實現的功能其實很簡單:消費Kafka
的訊息,寫入hive
。(我在寫全鏈路追蹤功能實時引擎用的是flink
,為了技術架構統一,我還是希望透過flink
來實現。)
flink
從1.9
開始支援hive
。到目前為止,flink
穩定的版本在1.16.0
,flink
支援hive
也就這兩年的事。
austin
所依賴的元件有很多(正常線上環境都會有這些元件,只是不用我們自己搭建而已)。各種元件的環境問題被我一一征服了,但有很大程度上的功勞是在docker-compose
上。
說到資料倉儲,第一時間肯定是想到hive
。雖然我沒裝過hadoop/hive/hdfs
大資料相關的元件,但稍微想想這都是複雜的。那安裝hive
自然就會想到有沒有docker
映象,一鍵安裝可多爽啊。
之前接入的flink
也是跑在docker
上的,把hive
也找個映象,兩者融合融合不就行了嘛?
想法很好,我就開幹了。
基礎知識
flink
和hive
融合,實際上是藉助hive catalog
來打通hive
。hive catalog
對接著hive metastore
(hive
儲存後設資料的地方)。
當我們使用flink
建立出的後設資料,會經由hive catalog
最終持久化到hive metastore
,同時我們會利用hive catalog
提供的介面對hive
進行寫入和讀取。
安裝hive環境
那時候簡單搜了下,還真被我找到了hive
的映象,沒想到這麼幸運,還是支援docker-compose
的,一鍵安裝,美滋滋。
https://github.com/big-data-europe/docker-hive
我就簡單複述下過程吧,比較簡單:
1、把倉庫拉到自己的伺服器上
git clone git@github.com:big-data-europe/docker-hive.git
2、進入到專案的資料夾裡
cd docker-hive
3、啟動專案
docker-compose up -d
一頓下載之後,可以發現就啟動成功了,透過docker ps
命令就看到執行幾個映象了。
沒錯,這就安裝好hive
了,是不是非常簡單。具體啟動了什麼,我們可以簡單看下docker-compose.yml
檔案的內容。
最後,我們可以連上hive
的客戶端,感受下快速安裝好hive
的成功感。
# 進入bash
docker-compose exec hive-server bash
# 使用beeline客戶端連線
/opt/hive/bin/beeline -u jdbc:hive2://localhost:10000
深陷迷霧
hive
安裝好了之後,我就馬不停蹄地想知道怎麼跟flink
進行融合了。我就搜了幾篇部落格看個大概,後來發現大多數部落格的內容其實就是翻譯了flink
官網的內容。
不過,翻部落格的過程中讓我大致瞭解了一點:如果我要使用flink
連線hive
,那我要手動把flink
連線hive
的jar
包匯入到flink/lib
目錄下。
說實話,這還是比較麻煩的。我還以為只需要在我的工程裡匯入相關的依賴就好了,沒想到還得自己手動把jar
包下來下來,然後傳入到flink
的安裝目錄下。
我吭哧吭哧地做了,但把我寫好的工程jar
包傳上去提交給jobmanager
不是缺這就是少那依賴。我相信我能搞掂,反正就是版本依賴的問題嘛,我在行的。
後面又發現在flink
工程專案裡用maven
引入hadoop
依賴是不夠的,flink
新版本里預設打的映象是沒有hadoop
的,要手動在flink
環境目錄下引入hadoop
。這個也是麻煩的,但只要我在映象裡下載些環境,也不是不能幹。
1、安裝vim
apt-get update
apt-get install vim
2、安裝hadoop
2.1、下載hadoop
wget https://archive.apache.org/dist/hadoop/common/hadoop-2.7.4/hadoop-2.7.4.tar.gz
2.2、解壓hadoop
tar -zxf hadoop-2.7.4.tar.gz
2.3、配置環境變數
vim /etc/profile
export HADOOP_HOME=/opt/hadoop-2.7.4
export PATH=$HADOOP_HOME/bin:$PATH
export HADOOP_CLASSPATH=`hadoop classpath`
source /etc/profile
2.4、在flink
的docker容器裡還得把.bashrc
也得改了才生效
過於樂觀的我,搞了10天左右吧,終於頂不住了,下定決心:我一定要統一版本,不能修修補補了,該什麼版本就走什麼版本,推倒從來吧。我就按著flink
官網來走,一步一步走下來不可能錯的吧!
flink
最新的版本是v1.17-SNAPSHOT
,那我就挑上一個穩定的版本就行了!順便一看,我之前寫全鏈路追蹤austin
接入flink
的時候,程式碼的還是14.3
版本。但管不了這麼多了,就用1.16.0
版本吧。
首先,我發現我的flink
映象拉取的是最新的版本image: flink:latest
。那我得找1.16.0
版本的docker-compose
來部署,版本就得統一,後面的事才好搞。這個好找,在官網很快就找到了:image: flink:1.16.0-scala_2.12
新的映象搞下來了以後,我又吭哧地把相關的jar
都手動地匯入到flink
容器裡。另外,我發現官網寫的pom
依賴,壓根就下載不下來的,這不對勁啊。
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-table-api-java-bridge_2.12</artifactId>
<version>1.16.0</version>
<scope>provided</scope>
</dependency>
我開始以為是我的maven
倉庫配置問題,找遍了倉庫在那個artifactId
下,最大的也就只有1.14.x
的版本。去找了下flink
的issue
,發現有人跟我一樣的問題。
https://github.com/apache/flink/pull/21553
繼續嘗試提交我自己寫好的flink.jar
。毫無意外地,又報錯了,有些是之前的報錯,我很快地就能解決掉。
我一想,意識到是哪裡沒做好了:hive
的版本,hadoop
的版本,flink
的版本這三者也要約束。那我轉頭一看,發現之前我從映象里拉下來hive
版本是2.3.2
,裡面裝的hadoop
版本是2.7.4
。於是,我又統一了這三者的版本。信心很足,感覺一定能成。
再次提交,還是有問題,瘋狂Google
但就是一直找不到解決方案。能查出來的資料,網上的全都是“原始”安裝部署的,就沒有透過flink docker
映象跟hive
融合的,而且也不是跨機器的(給出來的案例都是在同一臺機器上,我是hive
部署一臺機器上,flink
部署在另一臺機器上)。
花了幾天除錯還是解決不掉,怎麼搞呢?放棄又不甘心。咋整?繼續推倒重來唄。
在使用flink容器
除錯的過程中我已經發現了:
1、拉下來的docker
映象裡的內容,跟官網所描述的jar
包是有出入的,有的是要我手動去下載的。但當時我覺得既然版本已經限定了,那應該問題也不大。
2、hadoop
環境變數在flink docker
容器下很難除錯。每次重新推倒從來的時候,我都得手動配置一次,步驟也繁瑣。即便我掛載了相關的jar
包和整個目錄
3、flink
容器內重啟和啟動叢集環境不可控,老是出現奇奇怪怪的問題。
那這一次,我就不用docker-compose
部署flink
了,直接在centos
安裝部署flink
,繼續整。
隨著我每一次推倒重來,我就覺得我離成功越來越近越來越近。從環境變數報錯缺失CALSS_PATH
的問題,已經到了sql
的語法的問題,從sql
語法的問題到找不到遠端地址namenode can't found
的問題,從遠端地址的問題,到HDFS
呼叫不通的問題。最後,終於除錯成功了。
下面就記錄我能除錯成功的安裝過程,各種坑錯誤異常就不記錄了(篇幅問題),這裡也吐槽夠了。
安裝flink環境
1、下載flink
壓縮包
wget https://dlcdn.apache.org/flink/flink-1.16.0/flink-1.16.0-bin-scala_2.12.tgz
2、解壓flink
tar -zxf flink-1.16.0-bin-scala_2.12.tgz
3、修改該目錄下的conf
下的flink-conf.yaml
檔案中rest.bind-address
配置,不然遠端訪問不到8081
埠,將其改為0.0.0.0
rest.bind-address: 0.0.0.0
4、將flink
官網提到連線hive
所需要的jar
包下載到flink
的lib
目錄下(一共4個)
wget https://repo.maven.apache.org/maven2/org/apache/flink/flink-sql-connector-hive-2.3.9_2.12/1.16.0/flink-sql-connector-hive-2.3.9_2.12-1.16.0.jar
wget https://repo.maven.apache.org/maven2/org/apache/hive/hive-exec/2.3.4/hive-exec-2.3.4.jar
wget https://repo.maven.apache.org/maven2/org/apache/flink/flink-connector-hive_2.12/1.16.0/flink-connector-hive_2.12-1.16.0.jar
wget https://repo.maven.apache.org/maven2/org/antlr/antlr-runtime/3.5.2/antlr-runtime-3.5.2.jar
5、按照官網指示把flink-table-planner_2.12-1.16.0.jar
和flink-table-planner-loader-1.16.0.jar
這倆個jar
包移動其目錄;
mv $FLINK_HOME/opt/flink-table-planner_2.12-1.16.0.jar $FLINK_HOME/lib/flink-table-planner_2.12-1.16.0.jar
mv $FLINK_HOME/lib/flink-table-planner-loader-1.16.0.jar $FLINK_HOME/opt/flink-table-planner-loader-1.16.0.jar
6、把後續kafka
所需要的依賴也下載到lib
目錄下
wget https://repo1.maven.org/maven2/org/apache/flink/flink-connector-kafka/1.16.0/flink-connector-kafka-1.16.0.jar
wget https://repo1.maven.org/maven2/org/apache/kafka/kafka-clients/3.3.1/kafka-clients-3.3.1.jar
安裝hadoop環境
由於hive
的映象已經鎖死了hadoop
的版本為2.7.4
,所以我這邊flink
所以來的hadoop
也是下載2.7.4
版本
1、下載hadoop
壓縮包
wget https://archive.apache.org/dist/hadoop/common/hadoop-2.7.4/hadoop-2.7.4.tar.gz
2、解壓hadoop
tar -zxf hadoop-2.7.4.tar.gz
安裝jdk11
由於高版本的flink
需要jdk 11
,所以這邊安裝下該版本的jdk
:
yum install java-11-openjdk.x86_64
yum install java-11-openjdk-devel.x86_64
配置jdk、hadoop的環境變數
這一步為了能讓flink
在啟動的時候,載入到jdk
和hadoop
的環境。
1、編輯/etc/profile
檔案
vim /etc/profile
2、檔案內容最底下增加以下配置:
JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.17.0.8-2.el7_9.x86_64
JRE_HOME=$JAVA_HOME/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH PATH
export HADOOP_HOME=/root/hadoop-2.7.4
export PATH=$HADOOP_HOME/bin:$PATH
export HADOOP_CLASSPATH=`hadoop classpath`
3、讓配置檔案生效
source /etc/profile
austin資料倉儲工程程式碼
直接上austin
倉庫地址,文章篇幅就不貼程式碼了,該寫的註釋我都寫了。
http://gitee.com/zhongfucheng/austin
這個工程程式碼量非常少,一共就4個核心檔案pom.xml
/hive-site.xml
/AustinHiveBootStrap.java
,要使用的時候注意該兩處地方即可:
1、com.java3y.austin.datahouse.constants.DataHouseConstant#KAFKA_IP_PORT
將這裡改成自己的kafka
的ip
和port
2、hive-site.xml
檔案全域性替換掉hive_ip
為自己的hive
地址,一共兩處
部署工程程式碼到Flink
我們把jar
包上傳到伺服器,然後使用命令提交jar
包給flink
執行。也可以開啟flink
的管理後臺,在頁面上提交jar
包並啟動。我這裡就選擇使用命令的方式來提交,主要因為在外網透出flink的埠,很容器被攻擊(我已經重灌系統幾次了。。)
(flink
命令在$FLINK_HOME/bin
下)
./start-cluster.sh
./flink run austin-data-house-0.0.1-SNAPSHOT.jar
啟動Kafka生產者寫入測試資料
啟動消費者的命令(將ip
和port
改為自己伺服器所部署的Kafka資訊):
$KAFKA_HOME/bin/kafka-console-producer.sh --topic austinTraceLog --broker-list ip:port
輸入測試資料:
{"state":"1","businessId":"2","ids":[1,2,3],"logTimestamp":"123123"}
即將成功
到這一步,離勝利就非常近了,但還是有通訊的問題:flink
無法識別namenode
/namenode
與datanode
之間的通訊問題等等。於是我們需要做以下措施:
1、hive
在部署的時候,增加datanode
/namenode
的通訊埠,部署hive
使用這個docker-compose檔案的內容:
version: "3"
services:
namenode:
image: bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8
volumes:
- namenode:/hadoop/dfs/name
environment:
- CLUSTER_NAME=test
env_file:
- ./hadoop-hive.env
ports:
- "50070:50070"
- "9000:9000"
- "8020:8020"
datanode:
image: bde2020/hadoop-datanode:2.0.0-hadoop2.7.4-java8
volumes:
- datanode:/hadoop/dfs/data
env_file:
- ./hadoop-hive.env
environment:
SERVICE_PRECONDITION: "namenode:50070"
ports:
- "50075:50075"
- "50010:50010"
- "50020:50020"
hive-server:
image: bde2020/hive:2.3.2-postgresql-metastore
env_file:
- ./hadoop-hive.env
environment:
HIVE_CORE_CONF_javax_jdo_option_ConnectionURL: "jdbc:postgresql://hive-metastore/metastore"
SERVICE_PRECONDITION: "hive-metastore:9083"
ports:
- "10000:10000"
hive-metastore:
image: bde2020/hive:2.3.2-postgresql-metastore
env_file:
- ./hadoop-hive.env
command: /opt/hive/bin/hive --service metastore
environment:
SERVICE_PRECONDITION: "namenode:50070 datanode:50075 hive-metastore-postgresql:5432"
ports:
- "9083:9083"
hive-metastore-postgresql:
image: bde2020/hive-metastore-postgresql:2.3.0
ports:
- "5432:5432"
presto-coordinator:
image: shawnzhu/prestodb:0.181
ports:
- "8080:8080"
volumes:
namenode:
datanode:
2、在部署flink
伺服器上增加hosts
,有以下(ip
為部署hive
的地址):
127.0.0.1 namenode
127.0.0.1 datanode
127.0.0.1 b2a0f0310722
其中 b2a0f0310722
是datanode
的主機名,該主機名會隨著hive
的docker
而變更,我們可以登入namenode
的後臺地址找到其主機名。而方法則是在部署hive
的地址輸入:
http://localhost:50070/dfshealth.html#tab-datanode
3、把工程下的hive-site.xml
檔案複製到$FLINK_HOME/conf
下
4、hadoop
的配置檔案hdfs-site.xml
增加以下內容(我的目錄在/root/hadoop-2.7.4/etc/hadoop
)
<property>
<name>dfs.client.use.datanode.hostname</name>
<value>true</value>
<description>only cofig in clients</description>
</property>
5、啟動flink-sql
的客戶端:
./sql-client.sh
6、在sql
客戶端下執行以下指令碼命令,注:hive-conf-dir
要放在$FLINK_HOME/conf
下
CREATE CATALOG my_hive WITH (
'type' = 'hive',
'hive-conf-dir' = '/root/flink-1.16.0/conf'
);
use catalog my_hive;
create database austin;
7、重啟flink
叢集
./stop-cluster.sh
./start-cluster.sh
8、重新提交執行flink
任務
./flink run austin-data-house-0.0.1-SNAPSHOT.jar
資料視覺化
到上面為止,我們已經把資料寫入到hive
表了,我們是不可能每一次都在命令列視窗裡查詢hive
的資料。一般在公司裡都會有視覺化平臺供我們開發/數倉/資料分析師/運營 去查詢hive
的資料。
我簡單看了幾個開源的視覺化平臺:Superset
/Metabase
/DataEase
。最後選擇了Metabase
,無他,看著順眼一些。
部署Metabase
很簡單,也是使用docker
進行安裝部署,就兩行命令(後續我會將其加入到docker-compose
裡面)。
docker pull metabase/metabase:latest
docker run -d -p 5001:3000 --name metabase metabase/metabase
完了之後,我們就可以開啟5001
埠到Metabase
的後臺了。
我們可以在Metabase
的後臺新增presto
進而連線hive
去查詢記錄。
這個presto
服務我們在搭建hive
的時候已經一起啟動了,所以這裡直接使用就好了。
到這一步,我們就可以透過在頁面上寫sql
把訊息推送過程中埋點的明細資料查詢出來
最後
這資料倉儲整個安裝環境和除錯過程確實折騰人,多次推倒重來(甚至不惜重灌系統重來)。還好最後輸入Kafka
一條訊息,在hive
表裡能看到一條記錄,能看到結果之後,折騰或許是值得的。
如果想學Java專案的,強烈推薦我的開源專案訊息推送平臺Austin(8K stars) ,可以用作畢業設計,可以用作校招,可以看看生產環境是怎麼推送訊息的。開源專案訊息推送平臺austin倉庫地址:
訊息推送平臺?推送下發【郵件】【簡訊】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。
參考資料: