大家好,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 [email protected]: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倉庫地址:
消息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程序】【企業微信】【釘釘】等消息類型。
參考資料: