一、概述
Presto是一個Facebook開源的分布式SQL查詢引擎,适用于互動式分析查詢,資料量支援GB到PB位元組。客戶在使用Presto的時候發現單個叢集不能滿足業務需求,而建立多個Presto叢集之後,如何在叢集間排程任務就成為一個問題。在Presto中,一個Query執行周期内需要用戶端和服務端進行多次的HTTP請求,在多叢集模式下,如何保證同一個Query的請求都分發到同一個叢集呢?
Lyft為解決這個問題而開發了presto-gateway這個工具,并将它開源出來。(https://github.com/lyft/presto-gateway)
Presto-gateway 是在多個Presto叢集前的一個有狀态Load-balancer,Proxy和Router,它提供了透明的通路方法。如下圖:(内容來自于https://eng.lyft.com/presto-infrastructure-at-lyft-b10adb9db01)
pinterest 架構:
參考資料:
- Lyft 資料:https://eng.lyft.com/presto-infrastructure-at-lyft-b10adb9db01
- pinterest 資料:https://medium.com/pinterest-engineering/presto-at-pinterest-a8bda7515e52
【溫馨提示】如需擷取文章中使用到的鏡像和部署包,可關注我的公衆号【大資料與雲原生技術分享】回複【pgw】即可擷取。如上面兩個連結打不開,則需要借助”梯子“安全上網,”梯子“在公衆号上也有推薦哦,回複【ai】即可擷取推薦。
二、部署 mysql
Presto-gateway 使用 MySQL 來記錄後端Presto叢集和查詢曆史,是以我們需要先準備一台MySQL伺服器,自建或者托管的RDS均可。這裡使用mysql on k8s快速部署,不清楚的可以參考我這篇文章:【雲原生】MySQL on k8s 環境部署
# 1、下載下傳安裝包,注意修改鏡像位址
git clone https://gitee.com/hadoop-bigdata/mysql-on-k8s.git
# 2、先準備好鏡像
docker pull docker.io/bitnami/mysql:8.0.30-debian-11-r15
docker tag docker.io/bitnami/mysql:8.0.30-debian-11-r15 myharbor.com/bigdata/mysql:8.0.30-debian-11-r15
# mysqld-exporter
docker pull docker.io/bitnami/mysqld-exporter:0.14.0-debian-11-r33
docker tag docker.io/bitnami/mysqld-exporter:0.14.0-debian-11-r33 myharbor.com/bigdata/mysqld-exporter:0.14.0-debian-11-r33
# 3、安裝helm
wget https://get.helm.sh/helm-v3.9.4-linux-amd64.tar.gz
tar -xf helm-v3.9.4-linux-amd64.tar.gz
ln -s /opt/helm/linux-amd64/helm /usr/local/bin/helm
# 4、建立挂載目錄,可以修改chat包裡配置檔案修改路徑
mkdir -p /opt/bigdata/servers/mysql/data/data1
# 5、安裝mysql
helm install mysql ./mysql-on-k8s -n mysql --create-namespace
# 5、解除安裝(不執行)
helm uninstall mysql -n mysql
kubectl delete pod -n mysql `kubectl get pod -n mysql |awk 'NR>1{print $1}'` --force
kubectl patch ns mysql -p '{"metadata":{"finalizers":null}}'
kubectl delete ns mysql --force
建立 presto-gateway 庫
# 擷取mysql root密碼,一般企業裡使用非root使用者給應用使用。這裡為了友善,就直接用root了。
MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace mysql mysql -o jsonpath="{.data.mysql-root-password}" | base64 -d)
# 登入mysql
kubectl exec -it mysql-primary-0 -n mysql -- mysql -h mysql-primary.mysql.svc.cluster.local -uroot -p"$MYSQL_ROOT_PASSWORD"
三、部署多套 presto 叢集
這裡部署也部署在k8s上,有不清楚的可以參考我之前的文章:【雲原生】Presto/Trino on k8s 環境部署
trino 官網:https://trino.io/docs/current/installation/kubernetes.html
# 安裝
#helm install trino ./presto-on-k8s -n presto --create-namespace
# 更新
#helm upgrade trino ./presto -n presto
# 也可以通過官方提供的chat部署,如下:
# docker pull trinodb/trino:latest,當然最新版本410,可能下載下傳會很慢,關注我公衆号【大資料與雲原生技術分享】可擷取離線鏡像包。
helm repo add trino https://trinodb.github.io/charts
# 下載下傳離線包
docker pull trino/trino && tar -xf trino-0.10.0.tgz
helm install trino001 ./trino -n trino001 --create-namespace --set service.type=NodePort
helm install trino002 ./trino -n trino002 --create-namespace --set service.type=NodePort
# 解除安裝
helm uninstall trino001 -n trino001
helm uninstall trino002 -n trino002
NOTES
[root@local-168-182-110 presto-gateway]# helm install trino001 ./trino -n trino001 --create-namespace --set service.type=NodePort
NAME: trino001
LAST DEPLOYED: Sun Mar 19 10:09:46 2023
NAMESPACE: trino001
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Get the application URL by running these commands:
export NODE_PORT=$(kubectl get --namespace trino001 -o jsonpath="{.spec.ports[0].nodePort}" services trino001)
export NODE_IP=$(kubectl get nodes --namespace trino001 -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
[root@local-168-182-110 presto-gateway]# helm install trino002 ./trino -n trino002 --create-namespace --set service.type=NodePort
NAME: trino002
LAST DEPLOYED: Sun Mar 19 10:10:08 2023
NAMESPACE: trino002
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Get the application URL by running these commands:
export NODE_PORT=$(kubectl get --namespace trino002 -o jsonpath="{.spec.ports[0].nodePort}" services trino002)
export NODE_IP=$(kubectl get nodes --namespace trino002 -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
[root@local-168-182-110 presto-gateway]#
檢視
kubectl get pods -A
helm get notes trino001 -n trino001
helm get notes trino002 -n trino002
export NODE_PORT=$(kubectl get --namespace trino001 -o jsonpath="{.spec.ports[0].nodePort}" services trino001)
export NODE_IP=$(kubectl get nodes --namespace trino001 -o jsonpath="{.items[0].status.addresses[0].address}")
https://$NODE_IP:$NODE_PORT
四、部署 presto-gateway 與簡單使用
1)下載下傳
git clone https://github.com/lyft/presto-gateway.git
2)Maven 編譯
# 安裝maven
wget https://dlcdn.apache.org/maven/maven-3/3.9.1/binaries/apache-maven-3.9.1-bin.tar.gz --no-check-certificate
tar -zvxf apache-maven-3.9.1-bin.tar.gz
ln -s `pwd`/apache-maven-3.9.1/bin/mvn /sbin/mvn
# 安裝jdk
tar -xf jdk-8u212-linux-x64.tar.gz
# /etc/profile檔案中追加如下内容:
echo "export JAVA_HOME=`pwd`/jdk1.8.0_212" >> /etc/profile
echo "export PATH=\$JAVA_HOME/bin:$PATH" >> /etc/profile
echo "export CLASSPATH=.:\$JAVA_HOME/lib/dt.jar:\$JAVA_HOME/lib/tools.jar" >> /etc/profile
# 加載生效
source /etc/profile
# 開始編譯
cd presto-gateway
mvn clean install
3)修改配置
先更改 gateway-ha 目錄下配置檔案 gateway-ha-config.yml,先查詢mysql資訊,登入mysql建立資料庫
# 擷取對外端口
kubectl get svc -n mysql
# 擷取mysql root密碼
MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace mysql mysql -o jsonpath="{.data.mysql-root-password}" | base64 -d)
echo $MYSQL_ROOT_PASSWORD
# 登入mysql
mysql -h 192.168.182.110 -P30306 -uroot -p"$MYSQL_ROOT_PASSWORD"
# 建立庫
create database prestogateway;
# 檢視
show databases;
修改配置 gateway-ha/gateway-ha-config.yml
dataStore:
jdbcUrl: jdbc:mysql://192.168.182.110:30306/prestogateway
user: root
password: wQKFKLi6By
driver: com.mysql.cj.jdbc.Driver
4)sql 初始化
# 擷取mysql root密碼
MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace mysql mysql -o jsonpath="{.data.mysql-root-password}" | base64 -d)
# 登入mysql
mysql -h 192.168.182.110 -P30306 -uroot -p"$MYSQL_ROOT_PASSWORD"
use prestogateway;
source ./gateway-ha/target/classes/gateway-ha-persistence.sql;
5)啟動服務
# check檢查配置
java -jar ./gateway-ha/target/gateway-ha-1.9.5-jar-with-dependencies.jar check ./gateway-ha/gateway-ha-config.yml
# 啟動服務
nohup java -jar ./gateway-ha/target/gateway-ha-1.9.5-jar-with-dependencies.jar server ./gateway-ha/gateway-ha-config.yml &
web 通路:http://<server-ip>:8090/entity
6)增加和修改presto叢集
可以通過兩種方式來将Presto叢集添加進來,如果名字相同,則可以更新現有資訊。
1、通過CURL指令
擷取presto對我端口
kubectl get svc -n trino001
kubectl get svc -n trino002
# 預設排程(routingGroup=adhoc)
curl -X POST http://localhost:8080/entity?entityType=GATEWAY_BACKEND \
-d '{ "name": "adhoc001",
"proxyTo": "http://192.168.182.110:30792",
"active": true,
"routingGroup": "adhoc"
}'
curl -X POST http://localhost:8080/entity?entityType=GATEWAY_BACKEND \
-d '{ "name": "adhoc002",
"proxyTo": "http://192.168.182.110:31258",
"active": true,
"routingGroup": "adhoc"
}'
# 配置presto1,presto2
curl -X POST http://localhost:8080/entity?entityType=GATEWAY_BACKEND \
-d '{ "name": "presto1",
"proxyTo": "http://192.168.182.110:30792",
"active": true,
"routingGroup": "presto1"
}'
curl -X POST http://localhost:8080/entity?entityType=GATEWAY_BACKEND \
-d '{ "name": "presto2",
"proxyTo": "http://192.168.182.110:31258",
"active": true,
"routingGroup": "presto2"
}'
2、通過Web UI
位址:http://<server-ip>:8090/entity
7)presto叢集清單
curl -X GET http://localhost:8080/gateway/backend/active | python -m json.tool
8)上線和下線presto叢集
# 下線
curl -X POST http://localhost:8080/gateway/backend/deactivate/presto2
# 上線
curl -X POST http://localhost:8080/gateway/backend/activate/presto2
9)删除presto叢集
curl -X POST http://localhost:8080/gateway/backend/deactivate/presto1
10)路由規則
Presto-gateway提供了使用者可以自定義路由規則的功能來重定向請求到不同叢集,這個規則可以通過修改配置檔案(gateway-ha/gateway-ha-config.yml)來設定。
routingRules:
rulesEngineEnabled: true
rulesConfigPath:"src/test/resources/rules/routing_rules.yml" # replace with path toyour rules config file
- 預設情況下(預設rulesEngineEnabled是false),presto-gateway讀取X-Trino-Routing-Group請求頭來路由請求。如果沒有指定這個報頭,請求被發送到預設路由組(adhoc)。
- 路由規則引擎根據請求資訊(如任何請求頭)編寫自定義邏輯來路由請求。路由規則與presto-gateway應用程式代碼分離到配置檔案中,允許動态更改規則。
1、定義路由規則
為了更好的觸發路由規則,我們使用了easy-rules(https://github.com/j-easy/easy-rules/wiki/defining-rules#composite-rules) 引擎。這些規則應該存儲在YAML檔案中。規則由name、description、condition和actions(操作清單)組成。如果特定規則的條件計算結果為true,則觸發其動作。配置檔案:src/test/resources/rules/routing_rules.yml
---
name: "presto1"
description: "if query from airflow, route to etl group"
priority: 0
condition: "request.getHeader(\"X-Trino-Source\") == \"presto1\""
actions:
- "result.put(\"routingGroup\", \"presto1\")"
---
name: "presto2"
description: "if query from airflow with special label, route to etl-special group"
priority: 1
condition: "request.getHeader(\"X-Trino-Source\") == \"presto2\""
actions:
- "result.put(\"routingGroup\", \"presto2\")"
【注意】請求頭可以通過 HttpServletRequest 或者 nginx轉發設定。每個規則必須至少有一個action,表示前面的condition滿足後,要執行的步驟。例如上面的cetus_adhoc_search,定義表明如果請求來源于cetus,就轉發路由給adhoc presto叢集組處理。
優先級(priority):整數越低,優先級越高。如果不指定優先級,則預設為INT_MAX。
五、測試驗證
1)下載下傳 presto 用戶端
# cli 用戶端
wget https://repo1.maven.org/maven2/io/trino/trino-cli/410/trino-cli-410-executable.jar
chmod +x trino-cli-410-executable.jar
# jdbc用戶端
wget https://repo1.maven.org/maven2/io/trino/trino-jdbc/410/trino-jdbc-410.jar
chmod +x trino-jdbc-410.jar
2)示例示範
1、通過CLI用戶端通路presto-gateway
通過presto-gateway去查詢presto叢集資訊
# https://gatewayhost:8080
./trino-cli-410-executable.jar --server http://192.168.182.110:8080 --user=admin --execute "select * from system.runtime.nodes;"
2、通過上下線來切換調用的叢集
# 下線
curl -X POST http://localhost:8080/gateway/backend/deactivate/presto1
# 上線
curl -X POST http://localhost:8080/gateway/backend/activate/presto1
當然也可以通過添加header的方式進行定點調用。
【注意】如果未指定路由規則,則預設排程到adhoc,如果adhoc對應多個presto叢集,則會負載均衡,多個叢集會輪詢調用。
Presto-gateway 講解與實戰操作就先到這裡了,有任何疑問歡迎給我留言哦,後續會持續更新相關技術文章,有任何疑問歡迎留言或私信,也可以關注我的公衆号【大資料與雲原生技術分享】深入技術交流或私信咨詢問題~