引言
在資料驅動的世界中,企業正在尋求可靠且高效能的解決方案來管理其不斷增長的資料需求。本系列部落格從一個重視資料安全和合規性的 B2C 金融科技客戶的角度來討論雲上雲下混合部署的情況下如何利用亞馬遜雲科技雲原生服務、開源社群產品以及第三方工具構建無伺服器資料倉儲的解耦方法。
本篇部落格著重探討 EMR Serverless 的操作要點、最佳化以及開放整合測試。如有興趣,各位看官請看前幾篇文章回顧一下:
搜尋關鍵詞:
構建無伺服器數倉(二)Apache DolphinScheduler 整合以及 LOB 粒度資源消費分析
利用Amazon EMR Serverless、Athena與Dolphinscheduler構建雲上雲下資料同步方案
架構設計圖
EMR Serverless Job 操作要點
理解 Application 和 Job 的概念
EMR Serverless Application 是一個資源池的概念。應用程式擁有一定的計算能力, 記憶體以及供在其上執行的作業使用的儲存資源。資源容量也可以透過命令列和 Web 控制檯進行配置。
作為一個資源池,EMR 無伺服器應用程式的建立通常是一次性操作。一旦設定了引擎(spark/hive),就建立了一個應用程式,初始容量和最大容量已經規劃好。由於應用程式的建立並不頻繁,因此透過 Web 控制檯建立應用程式是一種可行的方式。
以下亞馬遜雲科技 CLI 示例命令顯示瞭如何建立 EMR 無伺服器應用程式:
aws emr-serverless create-application \
--type HIVE \
--name <specific application name> \
--release-label "emr-6.6.0" \
--initial-capacity '{
"DRIVER": {
"workerCount": 1,
"workerConfiguration": {
"cpu": "2vCPU",
"memory": "4GB",
"disk": "30gb"
}
},
"TEZ_TASK": {
"workerCount": 10,
"workerConfiguration": {
"cpu": "4vCPU",
"memory": "8GB",
"disk": "30gb"
}
}
}' \
--maximum-capacity '{
"cpu": "400vCPU",
"memory": "1024GB",
"disk": "1000GB"
}'
以下 snapshot 顯示瞭如何透過亞馬遜雲科技 Web 控制檯配置 EMR 無伺服器應用程式的資源容量:
EMR Serverless Job 是實際處理計算任務的工作單元。為了使作業正常執行,需要設定 EMR Serverless Application ID、執行 IAM 角色(稍後將介紹如何配置角色)、具體的應用程式配置(例如作業正在規劃的資源)使用)需要設定。
雖然 EMR Serverless 作業可以透過 Web 控制檯建立,但由於作業的生命週期比應用程式要短得多,因此建議透過命令列完成作業生命週期管理。
以下是將 EMR 無伺服器作業提交到 EMR 無伺服器引擎的示例亞馬遜雲科技 CLI 命令。
aws emr-serverless start-job-run \
--application-id $applicationId \
--execution-role-arn $JOB_ROLE_ARN \
--job-driver '{
"hive": {
"initQueryFile": "s3://<bucket name>/<specific prefix>/create_fdm_table.sql", #DDL SQL for instance
"query": "s3://<bucket name>/<specific prefix>/ingest_fdm_data.sql", #DML SQL for instance
"parameters": "--hiveconf hive.exec.scratchdir=s3://<bucket name>/hive/scratch --hiveconf hive.metastore.warehouse.dir=s3://<bucket name>/hive/warehouse"
}
}' \
--configuration-overrides '{
"applicationConfiguration": [
{
"classification": "hive-site",
"properties": {
"hive.driver.cores": "2",
"hive.driver.memory": "4g",
"hive.tez.container.size": "8192",
"hive.tez.cpu.vcores": "4"
}
}
],
"monitoringConfiguration": {
"s3MonitoringConfiguration": {
"logUri": "s3://<bucket name>/hive-logs/"
}
}
}'
EMR 無伺服器工作角色建立
作業角色需要有權訪問特定的 S3 儲存桶以讀取作業指令碼並可能寫入結果,同時需要有權訪問 Glue 以讀取儲存所有表後設資料的 Glue Catalog。
- 建立 IAM 角色
aws iam create-role --role-name emr-serverless-job-role --assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "emr-serverless.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
- 將角色附加到策略以啟用 S3 儲存桶訪問
aws iam put-role-policy --role-name emr-serverless-job-role --policy-name S3Access --policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadFromOutputAndInputBuckets",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::<specific bucket name>",
"arn:aws:s3:::<specific bucket name>/*"
]
},
{
"Sid": "WriteToOutputDataBucket",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::<specific bucket name>/*"
]
}
]
}'
- 將角色附加到策略以啟用 Glue 許可權
aws iam put-role-policy --role-name emr-serverless-job-role --policy-name GlueAccess --policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GlueCreateAndReadDataCatalog",
"Effect": "Allow",
"Action": [
"glue:GetDatabase",
"glue:GetDataBases",
"glue:CreateTable",
"glue:GetTable",
"glue:GetTables",
"glue:GetPartition",
"glue:GetPartitions",
"glue:UpdateTable",
"glue:CreatePartition",
"glue:BatchCreatePartition",
"glue:GetUserDefinedFunctions"
],
"Resource": ["*"]
}
]
}'
EMR Serverless Job 狀態監控
applicationId=$(redis cli GET applicationId_LOB1)
app_state{
response2=$(aws emr-serverless get-application --application-id $applicationId)
application=$(echo $response1 | jq -r '.application')
state=$(echo $application | jq -r '.state')
return state
}
state=app_state()
while [ $state!="CREATED" ]; do
state=app_state()
done
response2=$(emr-serverless start-application --application-id $applicationId)
state=app_state()
while [ $state!="STARTED" ]; do
state=app_state()
done
response3=$(aws emr-serverless start-job-run \
--application-id $applicationId \
--execution-role-arn $JOB_ROLE_ARN \
--job-driver '{
"hive": {
"initQueryFile": "s3://shiyang-noaa-gsod-pds/create_table_1.sql",
"query": "s3://shiyang-noaa-gsod-pds/extreme_weather_1.sql",
"parameters": "--hiveconf hive.exec.scratchdir=s3://<bucket name>/hive/scratch --hiveconf hive.metastore.warehouse.dir=s3://<bucket name>/hive/warehouse"
}
}' \
--configuration-overrides '{
"applicationConfiguration": [
{
"classification": "hive-site",
"properties": {
"hive.driver.cores": "2",
"hive.driver.memory": "4g",
"hive.tez.container.size": "8192",
"hive.tez.cpu.vcores": "4"
}
}
],
"monitoringConfiguration": {
"s3MonitoringConfiguration": {
"logUri": "s3://<bucket name>/hive-logs/"
}
}
}')
JOB_RUN_ID=$(echo $response3 | jq -r '.jobRunId')
#store job_run_id into redis
redis-cli SET job_run_id_LOB1 $JOB_RUN_ID
response4=$(aws emr-serverless get-job-run --application-id $applicationId --job-run-id $JOB_RUN_ID)
jobRun=$(echo $response4 | jq -r '.jobRun')
JOB_RUN_ID=$(echo $jobRun | jq -r '.jobRunId')
JOB_STATE=$(echo $jobRun | jq -r '.state')
EMR Serverless 最佳化
使用最新的 EMR 版本
強烈建議使用最新的 EMR 版本,因為最新版本具有最新的效能。截至目前(2024 年 4 月),EMR Serverless 最新版本為 emr-7.0.0。
利用 ARM 架構
強烈建議選擇 arm64 EMR 架構而不是 x86_64 EMR 架構,因為前者可以提供更具成本效益的效能。
將 Hive 作業轉換為 Spark SQL 作業
EMR Serverless 的 Hive 作業引擎是 Tez,這意味著 EMR Serverless 目前不支援 Hive on Spark。
在實踐中,我們發現即使在 EMR Serverless 上執行的 Hive on Tez 也比在客戶本地環境中執行的 Hive on Spark 更快。如果將 Hive Job 轉換為 Spark SQL Job 並利用 spark 引擎,作業的效能可以進一步提升。
由於這種 Hive SQL 轉換 Spark SQL 並不複雜,只需將 Hive SQL 包裝在 Spark 語句中即可,如果對價效比有硬性要求,這樣的轉換是相當可行的。
具體配置每個作業的資源配置,然後配置每個應用程式的資源配置
上述 3 種最佳化 EMR Serverless Job 效能的方法不需要考慮每個作業的具體上下文。
還有另一種實現 EMR Serverless 作業效能最佳化的方法,需要分析每個應用程式以及每個作業的容量利用率和執行時間。
如果在很短的時間(例如秒級)內完成一項複雜的工作,並且消耗非常大的資源池,例如數千個 vCPU,數萬 GB 記憶體,最佳化方向可能是將資源限制在一定水平,以使其具有可比性。低成本與工作完成時間的平衡。
開放整合測試
使用 scala 或 python(pyspark)在 spark 中進行傳統開發方式的先決條件是需要在工程師的膝上型電腦或專用於開發的主機上部署 IDE(可以是 VSCode 或 IntelliJ)。
工程師編寫程式碼並使用該機器上儲存的示例資料完成自測試。之後,如果用 scala 編寫,則應透過 sbt 將程式碼打包為 jar 檔案;如果用 pyspark 編寫,則應將程式碼打包為指令碼。
然後將 jar/script 檔案上傳到整合開發環境,透過執行 spark xxx.jar/xxx.py 命令,可以對程式碼進行整合測試。
這種對 spark 程式碼進行整合測試的方式是一種封閉的方式:如果在整合測試中發現了 bug,工程師不可能直接在整合開發環境中進行除錯,因為程式碼已經被包裝為 jar/指令碼檔案。
他/她必須透過他/她的自測試環境(部署在他/她的膝上型電腦上的 IDE)完成除錯工作。這種整合測試的方式會受到很大的影響,特別是當程式碼需要除錯相當長的時間才能達到正確的狀態時,考慮到業務邏輯本身很複雜。
EMR Serverless 提供 EMR Studio,可以實現開放的整合測試方式。該程式碼是透過 Jupyter 筆記本單元編寫和測試的。上游資料來源和下游資料目的地可以透過在單元中編寫程式碼來連線。然後,測試的程式碼可以打包為 Spark jar 檔案或 pyspark 指令碼檔案,最後作為 EMR 無伺服器作業提交。
步驟 1:建立 EMR Studio
步驟 2:建立一個 Interactive Application
透過按照下面的快照設定配置來建立互動式應用程式:
步驟 3:在 EMR Studio 下建立 Workspace
在 EMR Studio 下建立一個工作區,如下圖所示:
步驟 4:啟動工作區,並將筆記本與第二步中建立的互動式應用程式和上一節中建立的工作角色 attach 在一起
總結
Serverless 的數倉平臺的優勢總結如下:
(1)解決了原有平臺算力瓶頸問題,顯著地提升了平臺整體執行效率
原有的最長的資料處理任務需要十幾個小時才能完成。同樣的任務在新平臺上執行 2 – 3 個小時就可以完成)。
原有的 hive@cdh 即便已經使用 spark 作為引擎,同樣的 job 執行比新平臺要慢不止 4-5 倍。
(2)資料排程平臺和資料處理引擎、資料儲存介質完成了架構解耦,顯著地提高了平臺的健壯性和擴充套件性
原有的平臺,資料排程工具 DolphinScheduler,大資料叢集的計算和儲存都強耦合的執行在 CDH 叢集上。叢集的任何一個 module 出現問題,都可以導致叢集的不可用,進而導致其他 module 都不可用。
具體說,計算引擎和儲存是最容易出現問題的部分,如果原有的叢集出現了記憶體溢位或者儲存容量被打滿而導致叢集不可用的情況,會連帶地導致排程工具 DolphinScheduler 的不可用以及儲存或者計算的不可用。
新的平臺的解耦架構實現了排程工具、計算引擎、儲存介質的解耦,避免了這些問題。同時計算引擎採用 Serverless 架構,可以根據 Job 的需要動態的進行最優的算力匹配。儲存介質的 S3 也可以進行幾乎無限制的擴容,保證業務的需要。
(3)新平臺為後續的精細化運營提供了可能
新平臺可以在面向集團不同部門開放資料應用的同時,實現不同部門不同人的精細化許可權管控:不同的人根據其許可權的不同看到的資料資產的內容是不同的。同時,新平臺可以針對不同的業務部門進行財務成本的分攤核算。
(4)新平臺顯著降低了整合開發成本
新平臺同時支援 Spark 和 Hive,原來平臺的開發方式在新平臺上可以平移,無需增加任何成本。新平臺在此基礎上提供了 Serverless 的 EMR Studio 的方式,可以在平臺上進行開放式(而非打 jar 包)程式碼整合除錯,降低了開發成本。
本文由 白鯨開源 提供釋出支援!