原始碼編譯,Apache DolphinScheduler前後端分離部署解決方案

海豚调度發表於2024-08-27

file

轉載自神龍大俠

生產環境部署方案

在企業線上生產環境中,普遍的做法是至少實施兩套環境。

  1. 測試環境
  2. 線上環境

測試環境用於驗證程式碼的正確性,當測試環境驗證ok後才會部署線上環境。

鑑於CI/CD應用的普遍性,原始碼一鍵部署是必要的。

本文是探索對DolphinScheduler原始碼改造,構建測試,線上雙環境一鍵部署和上線。

同時,我對dolphinscheduler-api進行改造,使得前端管理系統前後端分離,以使得部署更貼近生產環境,方便生產環境元件橫向部署,這也讓前後端並行程式碼開發更加便利。

如果熟悉DolphinScheduler的同學可以前面的介紹,直接跳到部署方案那裡看起。

DolphinScheduler介紹

Apache DolphinScheduler 是一個分散式易擴充套件的視覺化DAG工作流任務排程開源系統。適用於企業級場景,提供了一個視覺化操作任務、工作流和全生命週期資料處理過程的解決方案。

Apache DolphinScheduler 旨在解決複雜的大資料任務依賴關係,併為應用程式提供資料和各種 OPS 編排中的關係。 解決資料研發ETL依賴錯綜複雜,無法監控任務健康狀態的問題。 DolphinScheduler 以 DAG(Directed Acyclic Graph,DAG)流式方式組裝任務,可以及時監控任務的執行狀態,支援重試、指定節點恢復失敗、暫停、恢復、終止任務等操作。

工作流定義啟動流程

很絲滑有木有(這裡面沒有alert-server的位置,不過這個也不負責具體的任務執行)

file

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容錯的相關邏輯;

  • worker-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-ui

系統的前端頁面,提供系統的各種視覺化操作介面。

部署方案

DolphinScheduler部署主要有四種:

  • 單機部署(Standalone)
  • 偽叢集部署(Pseudo-Cluster)
  • 叢集部署(Cluster)
  • 快速試用 Kubernetes 部署

其中單機部署主要是用於操作體驗,並不能執行工作流排程。

官網部署指南:https://dolphinscheduler.apache.org/zh-cn/docs/3.2.2/��%A...

DolphinScheduler官網提供了二進位制檔案部署,這種我也試了一下,安裝流程很流暢,不過還是沒有采用這種部署方案,主要考慮後面產品或者業務會提一些需求,需要這邊基於最新的版本做一些開發。

最終決定採用如下兩套部署方案:

  • 偽叢集部署方案 作為測試環境(stag)
  • 叢集部署方案 作為線上環境(prod)

下文用stag和prod作為測試環境和線上環境標誌。

原始碼開發pom管理有兩種方案:

  1. 升級版本資訊3.2.1到3.2.2
  2. 使用snapshot版本

為了不跟主線混淆主版本,也是致敬經典,我就使用snapshot作為後續的開發迭代版本了。

修改pom版本

本文基於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_HOMEPYTHON_LAUNCHERHADOOP_CLASSPATHSPARK_DIST_CLASSPATHHADOOP_CLIENT_OPTSSPARK_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_prodapi-ui_stagdolphinscheduler-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

file

釘釘報警和最佳化

目前我這報警主要是釘釘報警,釘釘報警可以發到群報警機器人,並且支援@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配置資訊,使用者名稱,密碼等。

本文由 白鯨開源 提供釋出支援!

相關文章