从安装到实操,Apache DolphinScheduler 关键脚本详解

本文将逐步解析DolphinScheduler的关键脚本。
176654190728277e66b23c7f6f455



点击蓝字 关注我们



在现代数据处理和工作流管理中,Apache DolphinScheduler以其灵活性和强大的调度能力受到开发者的广泛欢迎。

本文将逐步解析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$hosttest -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

# 定义了一个函数,具体看后面的使用,覆盖环境变量
functionoverwrite_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=""
functionget_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$startStopin
(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`
ifkill -0 $TARGET_PID > /dev/null 2>&1; then
echo stopping $command
pkill -P $TARGET_PID
sleep $STOP_TIMEOUT
ifkill -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,从而提升数据工作流的效率和稳定性。随着技术的不断进步,了解并掌握这些基本的脚本操作对于保持技术竞争力是至关重要的。


17665419243980cb7b8f906123948
176654192478370063fc7a930f881
17665419243980cb7b8f906123948

1766541925684b0af496dea826c2f



用户案例



天翼云Zoom网易邮箱
每日互动 惠生工程 作业帮
博世智驾 蔚来汽车 长城汽车
集度长安汽车思科网讯
食行生鲜联通医疗联想
新网银行唯品富邦消费金融
自如有赞伊利当贝大数据
珍岛集团传智教育Bigo
YY直播 拈花云科太美医疗
Cisco Webex兴业证券


1766541925684b0af496dea826c2f



迁移实战



Azkaban Ooize(当贝迁移案例)
airflow (有赞迁移案例)
Air2phin(迁移工具)
Airflow迁移实践

1766541925684b0af496dea826c2f



发版消息




Apache DolphinScheduler 3.2.2版本正式发布!
Apache DolphinScheduler 3.2.1 版本发布:增强功能与安全性的全面升级
Apache DolphinScheduler 3.3.0 Alpha发布,功能增强与性能优化大升级!


1766541925684b0af496dea826c2f



加入社区



关注社区的方式有很多:

  • GitHub: https://github.com/apache/dolphinscheduler
  • 官网:https://dolphinscheduler.apache.org/en-us
  • 订阅开发者邮件:dev@dolphinscheduler@apache.org(向邮箱发送任意内容,收到邮件后回复同意订阅即可)
  • X.com:@DolphinSchedule
  • YouTube:https://www.youtube.com/@apachedolphinscheduler
  • Slack:https://join.slack.com/t/asf-dolphinscheduler/shared_invite/zt-1cmrxsio1-nJHxRJa44jfkrNL_Nsy9Qg

同样地,参与Apache DolphinScheduler 有非常多的参与贡献的方式,主要分为代码方式和非代码方式两种。

非代码方式包括:

完善文档、翻译文档;翻译技术性、实践性文章;投稿实践性、原理性文章;成为布道师;社区管理、答疑;会议分享;测试反馈;用户反馈等。

‍代码方式包括:

查找Bug;编写修复代码;开发新功能;提交代码贡献;参与代码审查等。

贡献第一个PR(文档、代码) 我们也希望是简单的,第一个PR用于熟悉提交的流程和社区协作以及感受社区的友好度。

社区汇总了以下适合新手的问题列表https://github.com/apache/dolphinscheduler/pulls?q=is%3Apr+is%3Aopen+label%3A%22first+time+contributor%22

优先级问题列表https://github.com/apache/dolphinscheduler/pulls?q=is%3Apr+is%3Aopen+label%3Apriority%3Ahigh

如何参与贡献链接https://dolphinscheduler.apache.org/zh-cn/docs/3.2.2/%E8%B4%A1%E7%8C%AE%E6%8C%87%E5%8D%97_menu/%E5%A6%82%E4%BD%95%E5%8F%82%E4%B8%8E_menu

如果你❤️小海豚,就来为我点亮Star吧!

https://github.com/apache/dolphinscheduler

176654192755033ce91bb9eaa4af7


17665419280506464bafe7d1de408

你的好友秀秀子拍了拍你

并请你帮她点一下“分享”