精細調度:Apache DolphinScheduler腳本深度解析

在現代數據處理和工作流管理中,Apache DolphinScheduler以其靈活性和強大的調度能力受到開發者的廣泛歡迎。

file

本文將逐步解析DolphinScheduler的關鍵腳本,希望能提供一個詳盡的操作指南,幫助大家掌握安裝、配置和操作的每一步。

建立在./bin/env/下目錄的配置文件建立好的前提。

安裝流程解析

./install.sh
  • 通過source獲取install_env.sh和dolphinscheduler_env.sh中的環境變量,如master、worker的基本信息。
  • 在當前機器上創建安裝目錄,並給目錄授權。
  • 向其他節點發送dolphinscheduler的解壓文件
  • 停止所有的服務
  • 刪除zk上的dolphinscheduler根節點
  • 啓動dolphinscheduler所有的服務。

拷貝文件到工作節點

    workDir=`dirname $0`
    workDir=`cd ${workDir};pwd`

    source ${workDir}/env/install_env.sh
    # 獲取workers=${workers:-"ds1:default,ds2:default,ds3:default,ds4:default,ds5:default"}
    # 獲取數組
    workersGroup=(${workers//,/ })
    # 順序取數組中的值
    for workerGroup in ${workersGroup[@]}
    do
    # 比如:ds1:default
      echo $workerGroup;
      # 獲取worker的ip
      worker=`echo $workerGroup|awk -F':' '{print $1}'`
      # 獲取worker對應ip的組,默認爲default
      group=`echo $workerGroup|awk -F':' '{print $2}'`
      # 將ip放置到一個集合
      workerNames+=($worker)
      # 組放到一個集合
      groupNames+=(${group:-default})
    done
    # 獲取需要安裝的機器ip: ips=${ips:-"ds1,ds2,ds3,ds4,ds5"}
    hostsArr=(${ips//,/ })
    # 開始遍歷所有需要安裝的機器
    for host in ${hostsArr[@]}
    do
      # 連接目標ip,驗證安裝目錄是否存在,如果不存在,則會進行文件夾的創建,因此,需要事先創建好ssh免密登錄
      if ! ssh -o StrictHostKeyChecking=no -p $sshPort $host test -e $installPath; then
      # 創建安裝目錄 比如:/home/dolphinscheduler/apache-dolphinscheduler
        ssh -o StrictHostKeyChecking=no -p $sshPort $host "sudo mkdir -p $installPath; sudo chown -R $deployUser:$deployUser $installPath"
      fi

      如果當前機器時server-worker的機器
      echo "scp dirs to $host/$installPath starting"
      for i in ${!workerNames[@]}; do
        if [[ ${workerNames[$i]} == $host ]]; then
          workerIndex=$i
          break
        fi
      done

      # 這裏表示用給定的組去替換default這個字符串,不過配置文件中,默認是不存在這個值的,暫時不用管
      # set worker groups in application.yaml
      [[ -n ${workerIndex} ]] && sed -i "s/- default/- ${groupNames[$workerIndex]}/" $workDir/../worker-server/conf/application.yaml

    # 將相關的七個文件都拷貝到安裝目錄下。
      for dsDir in bin master-server worker-server alert-server api-server ui tools
      do
        echo "start to scp $dsDir to $host/$installPath"
        # Use quiet mode to reduce command line output
        scp -q -P $sshPort -r $workDir/../$dsDir  $host:$installPath
      done
      # restore worker groups to default
      [[ -n ${workerIndex} ]] && sed -i "s/- ${groupNames[$workerIndex]}/- default/" $workDir/../worker-server/conf/application.yaml

      echo "scp dirs to $host/$installPath complete"
    done

Zookeeper上根節點的刪除

執行命令:

bash ${workDir}/remove-zk-node.sh $zkRoot

具體的腳本細節:

print_usage(){
        printf $"USAGE:$0 rootNode\n"
        exit 1
}
# 如果啓動參數的個數不等於1,就會報錯,
if [ $# -ne 1 ];then
        print_usage
fi
# 獲取zk上的rootNode: /dolphinscheduler
rootNode=$1

# 獲取當前 remove-zk-node.sh 腳本的目錄,bin
BIN_DIR=`dirname $0`
BIN_DIR=`cd "$BIN_DIR"; pwd`
# 獲取dolphin的根目錄,可能是安裝目錄,可能是包目錄
DOLPHINSCHEDULER_HOME=$BIN_DIR/..

# 刷新環境變量
source ${BIN_DIR}/env/install_env.sh
source ${BIN_DIR}/env/dolphinscheduler_env.sh

# 獲取java環境
export JAVA_HOME=$JAVA_HOME

# 設置配置文件目錄,不過不存在配置文件目錄
export DOLPHINSCHEDULER_CONF_DIR=$DOLPHINSCHEDULER_HOME/conf
# 獲取需要的lib包
export DOLPHINSCHEDULER_LIB_JARS=$DOLPHINSCHEDULER_HOME/api-server/libs/*

# 下面就是具體的執行命令:
export DOLPHINSCHEDULER_OPTS="-Xmx1g -Xms1g -Xss512k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:LargePageSizeInBytes=128m -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "
export STOP_TIMEOUT=5

CLASS=org.apache.zookeeper.ZooKeeperMain

exec_command="$DOLPHINSCHEDULER_OPTS -classpath $DOLPHINSCHEDULER_CONF_DIR:$DOLPHINSCHEDULER_LIB_JARS $CLASS -server $REGISTRY_ZOOKEEPER_CONNECT_STRING rmr $rootNode"

cd $DOLPHINSCHEDULER_HOME
$JAVA_HOME/bin/java $exec_command

# 下面來看下這個具體的執行命令是什麼?
/bin/java -Xmx1g -Xms1g -Xss512k 
-XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC 
-XX:+CMSParallelRemarkEnabled -XX:LargePageSizeInBytes=128m 
-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 
# 類路徑下的參數
-classpath /conf:/api-server/libs/* 
# 啓動的主要類
org.apache.zookeeper.ZooKeeperMain
# 啓動的相關參數,這個是zookeeper自身定義的東西,參數需要查看zookeepeer的類
# 主要是zookeeper的連接信息,主要從 dophinscheduler_env.sh 腳本中獲取的變量:export REGISTRY_ZOOKEEPER_CONNECT_STRING=${REGISTRY_ZOOKEEPER_CONNECT_STRING:-localhost:2181}
-server localhost:2181 rmr /dolphinscheduler

整體啓停流程解析

# 一鍵開啓集羣所有服務
bash ./bin/start-all.sh
# 一鍵關閉集羣所有服務
bash ./bin/stop-all.sh

啓動過程如下:

  • 通過source獲取install_env.sh中的變量,及api-server、master-server、worker-server、alert-server這幾個dolphin中節點的基本部署信息。
  • 通過ssh在各個節點上使用 dolphinscheduler-daemon.sh 命令對各個服務做啓停。
  • 啓停順序爲 master-server、worker-server、alert-server、api-server。
  • 啓動時最後會通過 status-all.sh 對各個服務的狀態做查詢。

節點狀態查詢解析

根據作者本人所瞭解的,獲取服務的狀態一般通過兩種方式:

  • 啓動服務時,將服務的進程id寫入到文件中,通常在/var/run/目錄中,當然,也可以自定義目錄。
  • 通過ps命令獲取對應的進程id。

當然,Apache DolphinScheduler也是通過寫進程文件pid的方式來獲取進程id來查詢服務狀態和停止服務的。

如何單節點啓停以及狀態查詢

在海豚調度的整個啓動,停止,狀態查詢中,最終所用到的腳本是 dolphinscheduler-daemon.sh

有時候,因爲某種原因,可能導致Apache DolphinScheduler集羣中某一個服務掛掉,不可能通過start-all.sh命令來操作所有,同時,在集羣各個服務的擴縮容中,也需要單節點啓動,因此合理使用該腳本就比較重要。

命令的使用規範:

dolphinscheduler-daemon.sh (start|stop|status) <api-server|master-server|worker-server|alert-server|standalone-server>

腳本解析

dolphinscheduler-daemon.sh 腳本

# 這是一個用法的示例
usage="Usage: dolphinscheduler-daemon.sh (start|stop|status) <api-server|master-server|worker-server|alert-server|standalone-server> "

# 攜帶的參數必須是兩個,如果是一個就會報錯
# if no args specified, show usage
if [ $# -le 1 ]; then
  echo $usage
  exit 1
fi

# 執行的命令
startStop=$1
# shift相當於是將$2 變成$1,
shift
# 執行的任務類型
command=$1
shift

echo "Begin $startStop $command......"

BIN_DIR=`dirname $0`
BIN_DIR=`cd "$BIN_DIR"; pwd`
# 獲取安裝路徑的家目錄,注意,因爲執行的時候,cd 到了installPath
DOLPHINSCHEDULER_HOME=`cd "$BIN_DIR/.."; pwd`
# 獲取dolphin的環境變量,爲下面的環境變量覆蓋做幫助
BIN_ENV_FILE="${DOLPHINSCHEDULER_HOME}/bin/env/dolphinscheduler_env.sh"

# 這段話的意思就是使用/bin/env/dolphinscheduler_env.sh配置文件,代替每個服務下配置目錄conf下的配置文件
# Overwrite server dolphinscheduler_env.sh in path `<server>/conf/dolphinscheduler_env.sh` when exists
# `bin/env/dolphinscheduler_env.sh` file. User could only change `bin/env/dolphinscheduler_env.sh` instead
# of each server's dolphinscheduler_env.sh when they want to start the server

# 定義了一個函數,具體看後面的使用,覆蓋環境變量
function overwrite_server_env() {
  local server=$1
  local server_env_file="${DOLPHINSCHEDULER_HOME}/${server}/conf/dolphinscheduler_env.sh"
  if [ -f "${BIN_ENV_FILE}" ]; then
    echo "Overwrite ${server}/conf/dolphinscheduler_env.sh using bin/env/dolphinscheduler_env.sh."
    cp "${BIN_ENV_FILE}" "${server_env_file}"
  else
    echo "Start server ${server} using env config path ${server_env_file}, because file ${BIN_ENV_FILE} not exists."
  fi
}

# 當前機器的hostname
export HOSTNAME=`hostname`
# 執行命令服務的日誌文件
export DOLPHINSCHEDULER_LOG_DIR=$DOLPHINSCHEDULER_HOME/$command/logs
# 設置超時時間
export STOP_TIMEOUT=5

# 創建日誌文件夾
if [ ! -d "$DOLPHINSCHEDULER_LOG_DIR" ]; then
  mkdir $DOLPHINSCHEDULER_LOG_DIR
fi

# 定義服務的啓動進程文件
pid=$DOLPHINSCHEDULER_HOME/$command/pid

# 進入到服務的主目錄
cd $DOLPHINSCHEDULER_HOME/$command
# 服務的運行日誌,out日誌
if [ "$command" = "api-server" ]; then
  log=$DOLPHINSCHEDULER_HOME/api-server/logs/$command-$HOSTNAME.out
elif [ "$command" = "master-server" ]; then
  log=$DOLPHINSCHEDULER_HOME/master-server/logs/$command-$HOSTNAME.out
elif [ "$command" = "worker-server" ]; then
  log=$DOLPHINSCHEDULER_HOME/worker-server/logs/$command-$HOSTNAME.out
elif [ "$command" = "alert-server" ]; then
  log=$DOLPHINSCHEDULER_HOME/alert-server/logs/$command-$HOSTNAME.out
elif [ "$command" = "standalone-server" ]; then
  log=$DOLPHINSCHEDULER_HOME/standalone-server/logs/$command-$HOSTNAME.out
else
  echo "Error: No command named '$command' was found."
  exit 1
fi

# 定義一個函數,獲取服務的當前狀態
state=""
function get_server_running_status() {
  state="STOP"
  if [ -f $pid ]; then
    TARGET_PID=`cat $pid`
    if [[ $(ps -p "$TARGET_PID" -o comm=) =~ "bash" ]]; then
      state="RUNNING"
    fi
  fi
}

# 使用case語句,根據情況做啓動,停止,狀態查看
case $startStop in
  (start)
    # if server is already started, cancel this launch
    # 如果服務已經啓動,直接退出啓動過程
    get_server_running_status
    if [[ $state == "RUNNING" ]]; then
      echo "$command running as process $TARGET_PID.  Stop it first."
      exit 1
    fi
    # 開始做啓動
    echo starting $command, logging to $DOLPHINSCHEDULER_LOG_DIR
    # 覆蓋配置文件
    overwrite_server_env "${command}"
    # 執行具體的命令,輸入到日誌文件,並將標準輸出2重定向到標準輸出1
    nohup /bin/bash "$DOLPHINSCHEDULER_HOME/$command/bin/start.sh" > $log 2>&1 &
    echo $! > $pid
    ;;

# 停止服務,通過kill命令
  (stop)
      if [ -f $pid ]; then
        TARGET_PID=`cat $pid`
        if kill -0 $TARGET_PID > /dev/null 2>&1; then
          echo stopping $command
          pkill -P $TARGET_PID
          sleep $STOP_TIMEOUT
          if kill -0 $TARGET_PID > /dev/null 2>&1; then
            echo "$command did not stop gracefully after $STOP_TIMEOUT seconds: killing with kill -9"
            pkill -P -9 $TARGET_PID
          fi
        else
          echo no $command to stop
        fi
        rm -f $pid
      else
        echo no $command to stop
      fi
      ;;

# 查詢狀態
  (status)
    get_server_running_status
    if [[ $state == "STOP" ]]; then
      #  font color - red
      state="[ \033[1;31m $state \033[0m ]"
    else
      # font color - green
      state="[ \033[1;32m $state \033[0m ]"
    fi
    echo -e "$command  $state"
    ;;

  (*)
    echo $usage
    exit 1
    ;;

啓動腳本關鍵點說明

這裏主要講一點關於env中配置目錄中的關鍵點,可以發現在dolphinscheduler_env.sh中有一些數據庫方面的配置。如下:

# Database related configuration, set database type, username and password
export DATABASE=${DATABASE:-postgresql}
export SPRING_PROFILES_ACTIVE=${DATABASE}
export SPRING_DATASOURCE_URL
export SPRING_DATASOURCE_USERNAME
export SPRING_DATASOURCE_PASSWORD

比較瞭解SpringBoot的同學知道,JAVA的配置一般是來自於Yaml文件中的,因此對於一些初試用的同學對配置可能就比較迷惑。

打開spring的官網: https://docs.spring.io/spring-boot/docs/2.2.9.RELEASE/reference/htmlsingle/#boot-features-external-config, 我們可以看到有這樣的描述:

SpringBoot使用一種非常特殊的PropertySource順序,旨在允許合理地覆蓋值。按以下順序考慮屬性:

  • $HOME/.config/spring-boot當 devtools 處於活動狀態時,文件夾中的Devtools全局設置屬性。
  • @TestPropertySource對你的測試進行註釋。
  • properties測試的屬性。可用於測試應用程序的特定部分的測試@SpringBootTest註釋。
  • 命令行參數。
  • 來自SPRING_APPLICATION_JSON(嵌入環境變量或系統屬性中的內聯 JSON)的屬性。
  • ServletConfig初始化參數。
  • ServletContext初始化參數。
  • JNDI 屬性來自java:comp/env.
  • Java 系統屬性 ( System.getProperties())。
  • 操作系統環境變量。
  • ARandomValuePropertySource僅在 中具有屬性random.*。
  • 打包的 jar(和 YAML 變體)之外的特定於配置文件的應用程序屬性application-{profile}.properties。
  • 特定於配置文件的應用程序屬性打包在 jar(application-{profile}.properties和 YAML 變體)內。
  • 打包的 jar(和 YAML 變體)之外的應用程序屬性application.properties。
  • 打包在 jar 內的應用程序屬性application.properties(和 YAML 變體)。
  • @PropertySource類上的註釋@Configuration。Environment請注意,在刷新應用程序上下文之前,不會將此類屬性源添加到中。現在配置某些屬性爲時已晚,例如在刷新開始之前讀取的logging.和。spring.main.
  • 默認屬性(由設置指定SpringApplication.setDefaultProperties)。

其中就有操作系統環境變量,而使用方式就是大寫和下劃線作爲分隔符,具體細節大家看鏈接的官網就明白了。

通過以上深入的腳本解析,開發者應能更加熟練地操縱Apache DolphinScheduler,從而提升數據工作流的效率和穩定性。隨着技術的不斷進步,瞭解並掌握這些基本的腳本操作對於保持技術競爭力是至關重要的。

本文由 白鯨開源科技 提供發佈支持!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章