生產環境部署方案
在企業線上生產環境中,普遍的做法是至少實施兩套環境。
- 測試環境
- 線上環境
測試環境用於驗證代碼的正確性,當測試環境驗證ok後才會部署線上環境。
鑑於CI/CD應用的普遍性,源代碼一鍵部署是必要的
本文是探索對dolphinscheduler源代碼改造,構建測試,線上雙環境一鍵部署和上線
同時對dolphinscheduler-api進行改造,使得前端管理系統前後端分離,以使得部署更貼近生產環境,方便生產環境組件橫向部署,同時這也讓前後端並行代碼開發更加便利。
如果熟悉dolphinscheduler的同學可以前面的介紹,直接跳到部署方案那裏看起
dolphinscheduler介紹
Apache DolphinScheduler 是一個分佈式易擴展的可視化DAG工作流任務調度開源系統。適用於企業級場景,提供了一個可視化操作任務、工作流和全生命週期數據處理過程的解決方案。
Apache DolphinScheduler 旨在解決複雜的大數據任務依賴關係,併為應用程序提供數據和各種 OPS 編排中的關係。 解決數據研發ETL依賴錯綜複雜,無法監控任務健康狀態的問題。 DolphinScheduler 以 DAG(Directed Acyclic Graph,DAG)流式方式組裝任務,可以及時監控任務的執行狀態,支持重試、指定節點恢復失敗、暫停、恢復、終止任務等操作。
工作流定義啓動流程
很絲滑有木有(這裏面沒有alert-server的位置,不過這個也不負責具體的任務執行)
dolphinscheduler核心模塊
在二進制文件部署方案中dolphinscheduler主要是有4個核心server如下
alert-server
提供告警服務,通過告警插件的方式實現豐富的告警手段。
master-server
MasterServer採用分佈式無中心設計理念,MasterServer主要負責 DAG 任務切分、任務提交監控,並同時監聽其它MasterServer和WorkerServer的健康狀態。 MasterServer服務啓動時向Zookeeper註冊臨時節點,通過監聽Zookeeper臨時節點變化來進行容錯處理。 MasterServer基於netty提供監聽服務。
該服務內主要包含:
DistributedQuartz分佈式調度組件,主要負責定時任務的啓停操作,當quartz調起任務後,Master內部會有線程池具體負責處理任務的後續操作;
MasterSchedulerService是一個掃描線程,定時掃描數據庫中的t_ds_command表,根據不同的命令類型進行不同的業務操作;
WorkflowExecuteRunnable主要是負責DAG任務切分、任務提交監控、各種不同事件類型的邏輯處理;
TaskExecuteRunnable主要負責任務的處理和持久化,並生成任務事件提交到工作流的事件隊列;
EventExecuteService主要負責工作流實例的事件隊列的輪詢;
StateWheelExecuteThread主要負責工作流和任務超時、任務重試、任務依賴的輪詢,並生成對應的工作流或任務事件提交到工作流的事件隊列;
FailoverExecuteThread主要負責Master容錯和Worker容錯的相關邏輯;
work-server
WorkerServer也採用分佈式無中心設計理念,WorkerServer主要負責任務的執行和提供日誌服務。 WorkerServer服務啓動時向Zookeeper註冊臨時節點,並維持心跳。 WorkerServer基於netty提供監聽服務。
api-server
API接口層,主要負責處理前端UI層的請求。該服務統一提供RESTful api向外部提供請求服務。
從嚴格意義上來講,api-server包含了兩個模塊,一個是後端接口api-server,一個是api-ui前端頁面。在dolphinscheduler的二進制部署方案中ApiServer和ui是合併打包的。
在實際的生產環境中一般前後端是分離部署,一個是縮小上線改動的影響範圍,上線效率更快,一個是前端和後端的部署機器沒必要都保持一樣的數量,分離部署更靈活,這個博文是使用最新的release版本3.2.1進行部署的。(2024年7月22日)
api-server
API接口層,主要負責處理前端UI層的請求。該服務統一提供RESTful api向外部提供請求服務。
api-ui
系統的前端頁面,提供系統的各種可視化操作界面。
部署方案
dolphinscheduler部署主要有四種
- 單機部署(Standalone)
- 偽集羣部署(Pseudo-Cluster)
- 集羣部署(Cluster)
- 快速試用 Kubernetes 部署
其中單機部署主要是用於操作體驗,並不能執行工作流調度
官網部署指南 https://dolphinscheduler.apache.org/zh-cn/docs/3.2.2/%E9%83%A...
dolphinscheduler官網提供了二進制文件部署,這種我也試了一下,安裝流程很流暢,不過還是沒有采用這種部署方案, 主要考慮後面產品或者業務會提一些需求,需要這邊基於最新的版本做一些開發
最終決定採用如下兩套部署方案
偽集羣部署方案 作為測試環境(stag)
集羣部署方案 作為線上環境(prod)
下文用stag和prod作為測試環境和線上環境標誌
源代碼開發pom管理有兩種方案
- 升級版本信息3.2.1到3.2.2
- 使用snapshot版本
為了不跟主線混淆主版本,也是致敬經典,我就使用snapshot作為後續的開發迭代版本了。
修改pom版本
本文基於最新的release版本3.2.1 統一改成了snapshot版本,這樣我自己修改的代碼,重新編譯之後可以在測試或者生產環境生效
<groupId>org.apache.dolphinscheduler</groupId>
<artifactId>dolphinscheduler</artifactId>
<version>3.2.100-SNAPSHOT</version>
備註:需要修改所有子模塊的pom版本信息
需要修改通用的環境配置信息
目前環境需要的依賴或者配置信息目錄在根目錄下的script/env下,/script/env下保存了測試環境和線上環境都要求一致的配置信息
如果確定使用mysql數據庫,需要引入jar包mysql-connector-java-8.0.33.jar
可以把mysql-connector-java-8.0.33.jar放在/script/env目錄下,這個測試和線上環境都是一致的配置和需求版本
另外一個主要的配置信息是dolphinscheduler_env.sh文件
dolphinscheduler_env.sh 配置各種路徑和環境變量信息
如果線上和測試環境配置不一樣的配置信息,可以分別創建測試和線上目錄,build的時候根據環境信息打包各自的配置文件
/script/env/stag
/script/env/prod
將線上和測試環境不同的配置信息dolphinscheduler_env.sh文件copy到這兩個目錄下
dolphinscheduler_env.sh文件包含的配置信息包括JAVA_HOME,PYTHON_LAUNCHER,HADOOP_CLASSPATH,SPARK_DIST_CLASSPATH,HADOOP_CLIENT_OPTS,SPARK_SUBMIT_OPTS等環境信息,根據實際情況配置好就ok了
我的stag環境dolphinscheduler_env.sh配置信息包括如下(這個根據自己的情況配置,不能直接copy哦)
export HADOOP_CLASSPATH=`hadoop classpath`:${DOLPHINSCHEDULER_HOME}/tools/libs/*
export SPARK_DIST_CLASSPATH=$HADOOP_CLASSPATH:$SPARK_DIST_CLASS_PATH
export HADOOP_CLIENT_OPTS="-javaagent:${DOLPHINSCHEDULER_HOME}/tools/libs/aspectjweaver-1.9.7.jar":$HADOOP_CLIENT_OPTS
export SPARK_SUBMIT_OPTS="-javaagent:${DOLPHINSCHEDULER_HOME}/tools/libs/aspectjweaver-1.9.7.jar":$SPARK_SUBMIT_OPTS
export FLINK_ENV_JAVA_OPTS="-javaagent:${DOLPHINSCHEDULER_HOME}/tools/libs/aspectjweaver-1.9.7.jar":$FLINK_ENV_JAVA_OPTS
export JAVA_HOME=${JAVA_HOME:-/usr/java/jdk1.8.0_181-amd64/}
export PYTHON_LAUNCHER=${PYTHON_LAUNCHER:-/usr/local/python3.7.2/bin/python3}
export SPRING_CACHE_TYPE=${SPRING_CACHE_TYPE:-none}
export SPRING_JACKSON_TIME_ZONE=${SPRING_JACKSON_TIME_ZONE:-UTC}
export MASTER_FETCH_COMMAND_NUM=${MASTER_FETCH_COMMAND_NUM:-10}
export PATH=$PYTHON_LAUNCHER:$JAVA_HOME/bin:$HADOOP_CLASSPATH:$SPARK_DIST_CLASSPATH:$FLINK_ENV_JAVA_OPTS:$PATH
備註jdk需要時1.8以上的版本
dolphinscheduler-api雙環境部署方案改造
對於alert-server,master-server,worker-server改造和dolphinscheduler-api改造一樣,這裏就不都一一例舉和分析了
增加線上和測試環境配置信息
刪除/dolphinscheduler-api/resources/application.yaml 這個是配置樣例,可以根據實際需要修改對應的配置信息。
添加測試環境配置信息
/dolphinscheduler-api/resources/stag/application.yaml
添加線上環境配置信息
/dolphinscheduler-api/resources/prod/application.yaml
application.yaml需要修改的內容包括(我列的這幾個是需要修改的項,其他的可以留着不動)
修改mysql對應配置
spring:
profiles:
active: mysql
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://ip:port/dolphinscheduler
username: user
password: pass
quartz:
properties:
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
修改zk對應的配置
registry:
type: zookeeper
zookeeper:
namespace: dolphinscheduler
connect-string: ip:port
retry-policy:
base-sleep-time: 60ms
max-sleep: 300ms
max-retries: 5
session-timeout: 30s
connection-timeout: 9s
block-until-connected: 600ms
digest: ~
增加雙環境jvm啓動參數信息
創建dolphinscheduler-api/src/main/bin/stag目錄,mv並修改jvm_args_env.sh配置信息
修改jvm_args_env.sh
-Xms1g
-Xmx1g
-Xmn512m
-XX:+IgnoreUnrecognizedVMOptions
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-Xloggc:gc.log
-XX:+ExitOnOutOfMemoryError
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=dump.hprof
-Duser.timezone=${SPRING_JACKSON_TIME_ZONE}
創建dolphinscheduler-api/src/main/bin/prod目錄,mv並修改jvm_args_env.sh配置信息
修改jvm_args_env.sh
-Xms8g
-Xmx8g
-Xmn2g
-XX:+IgnoreUnrecognizedVMOptions
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-Xloggc:gc.log
-XX:+ExitOnOutOfMemoryError
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=dump.hprof
-Duser.timezone=${SPRING_JACKSON_TIME_ZONE}
start.sh文件不用做改動,直接copy到對應的目錄即可
增加src/main/assembly/xml 線上和測試環境打包配置文件
dolphinscheduler-api-server-stag.xml
dolphinscheduler-api-server-prod.xml
<fileSet>
<directory>${basedir}/../../script/env</directory>
<outputDirectory>libs</outputDirectory>
<includes>
<include>mysql-connector-java-8.0.33.jar</include>
</includes>
<fileMode>0755</fileMode>
<directoryMode>0755</directoryMode>
</fileSet>
線上和測試環境一般不同所以需要根據路徑加載線上或者測試環境配置信息
對於測試環境
<fileSet>
<directory>${basedir}/src/main/resources/stag</directory>
<includes>
<include>*.yaml</include>
<include>*.xml</include>
</includes>
<outputDirectory>conf</outputDirectory>
</fileSet>
<fileSet>
<directory>${basedir}/src/main/bin/stag</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
<directoryMode>0755</directoryMode>
</fileSet>
線上環境
<fileSet>
<directory>${basedir}/src/main/resources/prod</directory>
<includes>
<include>*.yaml</include>
<include>*.xml</include>
</includes>
<outputDirectory>conf</outputDirectory>
</fileSet>
<fileSet>
<directory>${basedir}/src/main/bin/prod</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
<directoryMode>0755</directoryMode>
</fileSet>
修改pom文件
增加profile信息
<profiles>
<!--測試環境-->
<profile>
<id>stag</id>
<properties>
<spring.profiles.active>stag</spring.profiles.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!--生產環境-->
<profile>
<id>prod</id>
<properties>
<spring.profiles.active>prod</spring.profiles.active>
</properties>
</profile>
</profiles>
根據環境信息修改對應的assembly文件
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>dolphinscheduler-api-server</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<finalName>api-server</finalName>
<descriptors>
<descriptor>src/main/assembly/dolphinscheduler-api-server-${spring.profiles.active}.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
配置完上述信息之後,可以通過根據命令打包
線上:
mvn clean install -P prod '-Dmaven.test.skip=true' '-Dcheckstyle.skip=true' '-Dmaven.javadoc.skip=true'
測試:
mvn clean install -P stag '-Dmaven.test.skip=true' '-Dcheckstyle.skip=true' '-Dmaven.javadoc.skip=true'
如果需要根據pid文件判斷程序的健康檢查狀態並支持故障自動拉起的功能,可以修改 ApiApplicationServer的main方法,支持生成pid文件信息
public static void main(String[] args) {
ApiServerMetrics.registerUncachedException(DefaultUncaughtExceptionHandler::getUncaughtExceptionCount);
Thread.setDefaultUncaughtExceptionHandler(DefaultUncaughtExceptionHandler.getInstance());
SpringApplication application = new SpringApplicationBuilder(ApiApplicationServer.class).application();
application.addListeners(new ApplicationPidFileWriter("ApiServer.pid"));
application.run(args);
}
build之後,啓動執行sh bin/start.sh.
如果啓動報錯mysql表找不到,可以下載一下二進制安裝包,激活一下conf中的mysql數據庫,執行tools/bin/upgrade-schema.sh即可完成數據庫的初始化。
如果你修改代碼,且引入了一些jar包,然後報一些莫名其妙的錯誤,十有八九是jar包依賴版本錯亂了,將對應的jar包和官方代碼依賴的重複jar包 exlude出去就可以了。(最後如果有其他問題可以直接找我)
dolphinscheduler-ui部署方案
配置測試環境和線上環境後端接口api域名
修改.env.development 測試環境
VITE_APP_PROD_WEB_URL='https://stag.busi.com'
修改.env.production 測試環境
VITE_APP_PROD_WEB_URL='https://prod.busi.com'
這個地址是後端接口的域名前綴,也就是dolphinscheduler-api提供http接口的地址
修改package.json文件,在"build:prod"下面增加一行測試環境 build:stag命令
"build:prod": "vue-tsc --noEmit && vite build --mode production",
"build:stag": "vue-tsc --noEmit && vite build --mode development",
修改router
二進制文件打包默認目錄是/dolphinscheduler/ui,對於前後端分離部署,並沒有這個必要
修改src/router/index.ts代碼
const router = createRouter({
history: createWebHistory(
import.meta.env.MODE === 'production' ? '/' : '/'
),
routes
})
修改pom文件(增加build:stag)配置
<execution>
<id>pnpm run build:stag</id>
<goals>
<goal>pnpm</goal>
</goals>
<configuration>
<arguments>run build:stag</arguments>
</configuration>
</execution>
修改vite.config.ts文件中base目錄信息
二進制文件打包默認目錄是/dolphinscheduler/ui,對於前後端分離部署,並沒有這個必要
base: process.env.NODE_ENV === 'production' ? '/' : '/',
nginx配置信息
對於測試環境
server {
listen 你的port; # 自定義接口
server_name dolphinscheduler-test.buis.com;
root /home/deploy/api-ui_stag; #本地網站文件路徑
index index.html; #設置默認網頁
try_files $uri $uri/ /index.html;
location /dolphinscheduler {
proxy_pass http://api-server-ip:api-server-port;
}
}
對於線上環境
server {
listen 你的port; # 自定義接口
server_name dolphinscheduler-prod.buis.com;
root /home/deploy/api-ui_prod; #本地網站文件路徑
index index.html; #設置默認網頁
try_files $uri $uri/ /index.html;
location /dolphinscheduler {
proxy_pass http://api-server-ip:api-server-port;
}
}
其中api-ui_prod和api-ui_stag 為dolphinscheduler-ui build之後的dist目錄
nginx有一個配置非常關鍵
try_files $uri $uri/ /index.html;
由於dolphinscheduler-ui的vue router 模式為history模式,所有頁面的錄入都是通過域名根目錄進入的
例如
訪問https://dolphinscheduler-test.busi.com/目錄會跳轉到
https://dolphinscheduler-test.busi.com/home目錄,
但是你如果直接請求https://dolphinscheduler-test.busi.com/home會報404錯誤
解決的辦法 就是增加配置try_files $uri $uri/ /index.html;
同時去掉
location / {
}
配置
去掉location這個很關鍵
關於try_files的語法
Checks the existence of files in the specified order and uses the first found
file for request processing; the processing is performed in the current
context. The path to a file is constructed from the file parameter according
to the root and alias directives. It is possible to check directory’s
existence by specifying a slash at the end of a name, e.g. “$uri/”.
If none of the files were found, an internal redirect to the uri
specified in the last parameter is made.
參考
https://juejin.cn/post/6844903856359342087
大意就是它會按照try_files後面的參數依次去匹配root中對應的文件或文件夾。如果匹配到的是一個文件,那麼將返回這個文件;如果匹配到的是一個文件夾,那麼將返回這個文件夾中index指令指定的文件。最後一個uri參數將作為前面沒有匹配到的fallback。(注意try_files指令至少需要兩個參數)
build命令
測試環境打包:pnpm run build:stag
線上環境打包:pnpm run build:prod
最後執行
nginx -s reload
使得nginx部署生效
看一下效果
用户名:admin
密碼:dolphinscheduler123
釘釘報警和優化
目前我這報警主要是釘釘報警,釘釘報警可以發到羣報警機器人,並且支持@owner的功能
好用且不收費
原生的報警格式如下圖
start process success
[{"projectCode":14285493640640,"projectName":"xxx_test","owner":"admin",
"processId":12,"processDefinitionCode":14285512555584,
"processName":"flow_test1-1-20240717191405669","processType":"START_PROCESS",
"processState":"SUCCESS","modifyBy":"admin","recovery":"NO",
"runTimes":1,"processStartTime":"2024-07-17 19:14:05",
"processEndTime":"2024-07-17 19:14:09","processHost":"10.76.6.66:5678"}]
@xxx
我看起來感覺不太易讀,重新優化了一下報警格式,是不是看起來板正多了,後續可以考慮加一個鈎子,做一下中英文替換,或者直接修改報警源內容,看起來就更方便了。
start process success
projectCode:14285493640640
projectName:xxx_test
owner:admin
processId:22
processDefinitionCode:14371091350208
processName:testflow123-1-20240723111659147
processType:START_PROCESS
processState:SUCCESS
modifyBy:admin
recovery:NO
runTimes:1
processStartTime:2024-07-23 11:16:59
processEndTime:2024-07-23 11:17:00
processHost:10.76.6.66:5678
@xxx
備註:本文的一些關鍵配置信息我這隱掉了,每個公司的配置不一樣,參考自己公司的配置,
比如機器部署目錄,域名信息,mysql,zk配置信息,用户名,密碼等