一、问题描述
DolphinScheduler调度平台的UI界面加载缓慢,项目中的任务实例加载时间过长,需要解决这个问题,提高DolphinScheduler平台UI页面的加载速度。
二、原因分析
经过分析发现,任务实例过多是导致UI加载缓慢的主要原因。由于任务实例无法直接删除,根据文档了解到需要删除相应的工作流实例。删除工作流实例后,相关的任务实例和日志会自动被删除。然而,手动删除工作流实例耗时较长,因此不是一个有效的解决方案。为了提高效率,可以利用DolphinScheduler提供的API接口来实现删除操作,然后在DolphinScheduler平台上设置一个定时任务,定期清理工作流实例。可以编写Shell脚本或Python脚本来实现清理逻辑。
根据DolphinScheduler的API文档,进程实例(Process Instance)对应着UI页面中的工作流实例。因此,通过定时清理过期的进程实例,可以有效优化DolphinScheduler平台的UI加载速度。
三、解决方案
1. 设置API访问令牌
创建令牌步骤如下:
2. 逻辑分析
2.1 查找用于删除的API
查看DolphinScheduler的API文档,文档地址:http://localhost:12345/dolphinscheduler/swagger-ui/index.html。
找到进程实例相关操作的API,可以看到有两个进行删除操作的API,选择批量删除的接口/dolphinscheduler/projects/{projectCode}/process-instances/batch-delete
来执行删除操作。
需要两个参数。
- processInstanceIds:进程实例id的数组,用逗号分隔
- projectCode:项目代码
2.2 获取进程实例id的数组
可以从/dolphinscheduler/projects/{projectCode}/process-instances
接口获取进程实例的相关信息。
需要三个参数。
- pageNo:当前页
- pageSize:每页多少条数据
- projectCode:项目代码
2.3 获取项目代码
找到项目相关操作的API,可以使用/dolphinscheduler/projects/list
获取所有项目的一个列表信息,可以根据其中的项目名获得项目代码。
3. 代码实现
此代码将会清理所有项目4个月前1号到3个月前1号
的工作流实例。
3.1 shell代码实现
#!/bin/bash
# 认证令牌
token='5c7437968f5d4492dc694902d6e6847f'
# 链接
url='http://localhost:12345/dolphinscheduler'
# 每页多少条
page_size=10
# 三个月前日期时间
three_month_ago_datetime=$(date -d "-3 months" '+%Y-%m-01')
# 四个月前日期时间
four_month_ago_datetime=$(date -d "-4 months" '+%Y-%m-01')
# 获取所有项目名称
project_names=($(curl -X GET -H "token: ${token}" "${url}/projects/list" | jq -r '.data[] | "\(.name)"'))
# 循环获取项目名
for project_name in "${project_names[@]}"
do
echo "************************** 项目名: ${project_name} **************************"
# 根据项目名获取项目代码
project_code=$(curl -X GET -H "token: ${token}" "${url}/projects/list" | jq -r '.data[] | select(.name == '\""$project_name"\"') | .code')
# 总页数
total_page=$(curl -X GET -H "accept: */*" -H "token: ${token}" "${url}/projects/${project_code}/process-instances?endDate=${three_month_ago_datetime}%2000:00:00&pageNo=1&pageSize=${page_size}&startDate=${four_month_ago_datetime}%2000:00:00" | jq -r '.data.totalPage')
echo "************************** ${four_month_ago_datetime}~${three_month_ago_datetime} 时间的总页数: ${total_page} **************************"
for ((page_no=1; page_no<="$total_page"; page_no++))
do
echo "************************** 当前页: ${page_no} **************************"
# 根据项目代码、日期和页码等获取进程实例id,并用逗号分隔
ids=$(curl -X GET -H "accept: */*" -H "token: ${token}" "${url}/projects/${project_code}/process-instances?endDate=${three_month_ago_datetime}%2000:00:00&pageNo=1&pageSize=${page_size}&startDate=${four_month_ago_datetime}%2000:00:00" | jq -r '.data.totalList[].id' | tr '\n' ',')
echo "************************** id数组: ${ids} **************************"
# 根据ids批量删除进程实例(工作流实例)
curl -X POST -H "accept: */*" -H "token: ${token}" "${url}/projects/${project_code}/process-instances/batch-delete?processInstanceIds=${ids}"
echo "************************** ${project_name} 工作流实例删除成功 **************************"
done
done
exit 0
3.2 python代码实现
from datetime import datetime, timedelta
import requests
weeks_3_months_ago = 12
weeks_4_months_ago = 16
# 认证令牌
token = '5c7437968f5d4492dc694902d6e6847f'
# 链接
url = 'http://localhost:12345/dolphinscheduler'
# 每页多少条
page_size = 10
# 三个月前日期时间
three_month_ago_datetime = (datetime.now() - timedelta(weeks=weeks_3_months_ago)).strftime('%Y-%m-01')
# 四个月前日期时间
four_month_ago_datetime = (datetime.now() - timedelta(weeks=weeks_4_months_ago)).strftime('%Y-%m-01')
# 获取所有项目名称
response = requests.get(f"{url}/projects/list", headers={"token": token})
project_data = response.json()['data']
project_names = [project['name'] for project in project_data]
for project_name in project_names:
print(f"************************** 项目名: {project_name} **************************")
# 根据项目名获取项目代码
project_code = next((project['code'] for project in project_data if project['name'] == project_name), None)
if project_code:
# 总页数
response = requests.get(f"{url}/projects/{project_code}/process-instances",
headers={"accept": "*/*", "token": token},
params={"endDate": f"{three_month_ago_datetime} 00:00:00",
"startDate": f"{four_month_ago_datetime} 00:00:00",
"pageNo": 1,
"pageSize": f"{page_size}"})
total_page = response.json()['data']['totalPage']
print(
f"************************** {four_month_ago_datetime}~{three_month_ago_datetime} 时间的总页数: {total_page} **************************")
for page_no in range(1, total_page + 1):
print(f"************************** {project_name} : {page_no} **************************")
# 根据项目代码、日期和页码等获取进程实例id,并用逗号分隔
response = requests.get(f"{url}/projects/{project_code}/process-instances",
headers={"accept": "*/*", "token": token},
params={"endDate": f"{three_month_ago_datetime} 00:00:00",
"startDate": f"{four_month_ago_datetime} 00:00:00",
"pageNo": 1,
"pageSize": f"{page_size}"})
ids = ','.join([str(instance['id']) for instance in response.json()['data']['totalList']])
print(f"************************** id数组: {ids} **************************")
# 根据ids批量删除进程实例(工作流实例)
requests.post(f"{url}/projects/{project_code}/process-instances/batch-delete",
headers={"accept": "*/*", "token": token},
params={"processInstanceIds": ids})
print(f"************************** {project_name} 工作流实例删除成功 **************************")
print("All process instances deleted successfully.")