1. 为什么需要自动化清理历史数据与日志每次打开海豚调度系统时是不是总觉得页面加载越来越慢数据库查询耗时越来越长这很可能是因为系统运行过程中积累了大量历史工作流实例和日志文件。我负责维护的一个生产环境就遇到过这种情况——某天突然收到告警发现MySQL数据库磁盘使用率超过90%经排查发现t_ds_process_instance表竟然有上百万条记录。这些数据垃圾主要来自三个方面工作流实例记录每次工作流执行都会在MySQL生成记录任务实例记录每个任务节点执行会产生独立记录日志文件任务执行的详细日志存储在服务器本地如果不定期清理最直接的影响就是系统性能下降。我做过测试当process_instance表超过50万条时分页查询耗时从毫秒级飙升到3-5秒。更严重的是磁盘空间被占满会导致新任务无法执行。曾经有个凌晨2点的故障就是因为日志目录把inode用完了导致所有任务调度失败。2. 海豚调度清理机制原理解析2.1 官方清理功能局限性海豚调度自带的清理功能藏在项目管理→工作流实例页面可以通过手动勾选批量删除来清理。但实际使用中发现几个痛点只能按页选择每页50条处理大批量数据时操作繁琐删除操作不会同步清理关联的任务日志文件没有基于时间的筛选条件容易误删新实例# 官方前端删除操作的伪代码 def batch_delete(instance_ids): delete_from_database(instance_ids) # 只删除数据库记录 # 没有处理日志文件的操作2.2 关键API解析通过浏览器开发者工具抓包我发现核心API是POST /dolphinscheduler/projects/{projectCode}/process-instances/batch-delete这个接口设计有两点需要注意参数格式要求processInstanceIds123,456,789这样的逗号分隔字符串权限控制需要在Header中携带有效的token实测发现调用这个API会级联删除工作流实例记录t_ds_process_instance关联的任务实例记录t_ds_task_instance任务日志文件日志目录下的.log文件3. Python自动化清理脚本开发3.1 脚本整体架构我设计的脚本采用三层处理结构项目层获取有权限操作的项目列表工作流层按时间范围筛选可删除的实例删除层分批执行删除操作建议每批不超过100个def main(): projects get_projects() # 获取项目列表 for project in projects: instances get_instances(project, end_date) # 获取可删除实例 batch_delete(project, instances) # 分批删除3.2 关键代码实现认证处理推荐使用session保持方式session requests.Session() session.headers.update({ token: your_api_token, Content-Type: application/x-www-form-urlencoded })日期处理确保只删除过期数据from datetime import datetime, timedelta safe_date (datetime.now() - timedelta(days90)).strftime(%Y-%m-%d) if user_input_date safe_date: raise Exception(不能删除90天内的数据)批量删除注意API的限流处理def batch_delete(project_code, instance_ids): chunk_size 50 # 每批处理50条 for i in range(0, len(instance_ids), chunk_size): chunk instance_ids[i:i chunk_size] payload fprocessInstanceIds{,.join(chunk)} response session.post( f{base_url}/projects/{project_code}/process-instances/batch-delete, datapayload ) time.sleep(1) # 避免触发限流4. 生产环境部署方案4.1 Linux定时任务配置建议通过crontab设置凌晨低峰期执行# 每天凌晨3点执行清理保留60天数据 0 3 * * * /usr/bin/python3 /opt/scripts/dolphin_clean.py $(date -d 60 days ago \%Y-\%m-\%d)4.2 安全防护措施权限隔离创建专用账号并限制只有只读和删除权限操作日志脚本应记录详细执行日志删除保护建议先做dry-run验证# 安全验证示例 def dry_run(project_code, instance_ids): print(f[DryRun] 待删除实例({len(instance_ids)}个):) for i in instance_ids[:5]: # 只打印前5条 print(f - {i})4.3 监控与告警建议增加以下监控项数据库表空间增长率日志目录磁盘使用率清理脚本执行成功率可以在脚本退出时上报监控系统def report_metrics(deleted_count): requests.post(http://monitor/api, json{ metric: dolphin.clean, value: deleted_count, tags: fenv{os.getenv(ENV)} })5. 常见问题解决方案5.1 删除失败排查步骤当API返回错误时建议按以下顺序排查检查token是否过期HTTP 401确认实例状态是否为终态只允许删除成功/失败/停止的实例查看服务端日志是否有异常堆栈-- 查询非终态实例的SQL SELECT state, COUNT(*) FROM t_ds_process_instance WHERE start_time 2024-01-01 GROUP BY state;5.2 性能优化技巧对于超大规模集群10万实例建议按项目分片执行避免单次处理数据量过大使用多线程并发处理注意服务端承受能力对历史数据做归档而不是删除from concurrent.futures import ThreadPoolExecutor def parallel_delete(projects): with ThreadPoolExecutor(max_workers5) as executor: executor.map(clean_project, projects)5.3 版本兼容性处理不同版本API可能有差异推荐做法通过/dolphinscheduler/version接口获取版本号根据版本号启用不同处理逻辑对旧版本的特殊bug做兼容处理def get_version(): resp session.get(f{base_url}/dolphinscheduler/version) return resp.json()[data][version]这套方案在我们生产环境稳定运行了8个月累计自动清理超过300万条实例记录将数据库查询性能提升了5倍以上。最关键的是再也不用半夜起来处理磁盘告警了。如果你们团队也在用海豚调度强烈建议把这个自动化方案部署起来初期可以先在测试环境验证效果。