当前位置: 首页 > news >正文

Apache DolphinScheduler 限制秒级别的定时调度

背景

Apache DolphinScheduler 定时任务配置采用的 7 位 Crontab 表达式,分别对应秒、分、时、月天、月、周天、年

在团队日常开发工作中,工作流的定时调度一般不会细化到秒级别。但历史上出现过因配置的疏忽大意而产生故障时间,如应该配置每分钟执行的工作流被配置长了每秒执行,造成短时间内产生大量工作流实例,对 Apache DolphinScheduler 服务可用性和提交任务的 Hadoop 集群造成影响。

基于此,团队决定将 DolphinScheduler 中定时任务配置模块的 Crontab 表达式做限制,从平台侧杜绝此类事件发生

方案

我们的方案是从前后端双方面限制 Crontab 表达式的第一位:

  • 前端配置选择不提供“每一秒钟”选项
  • 服务端接口判断第一位为 * 时,返回错误

前端修改

在前端项目中,秒、分、时 均为统一模版(CrontabTime),因此新增 dolphinscheduler-ui/src/components/crontab/modules/second.tsx

只保留两种模式:intervalTimespecificTime

/** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements.  See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to You under the Apache License, Version 2.0* (the "License"); you may not use this file except in compliance with* the License.  You may obtain a copy of the License at**    http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import _ from 'lodash'
import { defineComponent, onMounted, PropType, ref, toRefs, watch } from 'vue'
import { NInputNumber, NRadio, NRadioGroup, NSelect } from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { ICrontabI18n } from '../types'
import { isStr, specificList } from '../common'
import styles from '../index.module.scss'const props = {timeMin: {type: Number as PropType<number>,default: 0},timeMax: {type: Number as PropType<number>,default: 60},intervalPerform: {type: Number as PropType<number>,default: 5},intervalStart: {type: Number as PropType<number>,default: 3},timeSpecial: {type: Number as PropType<number | string>,default: 60},timeValue: {type: String as PropType<string>,default: '*'},timeI18n: {type: Object as PropType<ICrontabI18n>,require: true}
}export default defineComponent({name: 'CrontabSecond',props,emits: ['update:timeValue'],setup(props, ctx) {const options = Array.from({ length: 60 }, (x, i) => ({label: i.toString(),value: i}))const timeRef = ref()const radioRef = ref()const intervalStartRef = ref(props.intervalStart)const intervalPerformRef = ref(props.intervalPerform)const specificTimesRef = ref<Array<number>>([])/*** Parse parameter value*/const analyticalValue = () => {const $timeVal = props.timeValue// Interval timeconst $interval = isStr($timeVal, '/')// Specific timeconst $specific = isStr($timeVal, ',')// Positive integer (times)if (($timeVal.length === 1 ||$timeVal.length === 2 ||$timeVal.length === 4) &&_.isInteger(parseInt($timeVal))) {radioRef.value = 'specificTime'specificTimesRef.value = [parseInt($timeVal)]return}// Interval timesif ($interval) {radioRef.value = 'intervalTime'intervalStartRef.value = parseInt($interval[0])intervalPerformRef.value = parseInt($interval[1])timeRef.value = `${intervalStartRef.value}/${intervalPerformRef.value}`return}// Specific timesif ($specific) {radioRef.value = 'specificTime'specificTimesRef.value = $specific.map((item) => parseInt(item))return}}// Interval start time(1)const onIntervalStart = (value: number | null) => {intervalStartRef.value = value || 0if (radioRef.value === 'intervalTime') {timeRef.value = `${intervalStartRef.value}/${intervalPerformRef.value}`}}// Interval execution time(2)const onIntervalPerform = (value: number | null) => {intervalPerformRef.value = value || 0if (radioRef.value === 'intervalTime') {timeRef.value = `${intervalStartRef.value}/${intervalPerformRef.value}`}}// Specific timeconst onSpecificTimes = (arr: Array<number>) => {specificTimesRef.value = arrif (radioRef.value === 'specificTime') {specificReset()}}// Reset interval timeconst intervalReset = () => {timeRef.value = `${intervalStartRef.value}/${intervalPerformRef.value}`}// Reset specific timeconst specificReset = () => {let timeValue = '0'if (specificTimesRef.value.length) {timeValue = specificTimesRef.value.join(',')}timeRef.value = timeValue}const updateRadioTime = (value: string) => {switch (value) {case 'intervalTime':intervalReset()breakcase 'specificTime':specificReset()break}}watch(() => timeRef.value,() => ctx.emit('update:timeValue', timeRef.value.toString()))onMounted(() => analyticalValue())return {options,radioRef,intervalStartRef,intervalPerformRef,specificTimesRef,updateRadioTime,onIntervalStart,onIntervalPerform,onSpecificTimes,...toRefs(props)}},render() {const { t } = useI18n()return (<NRadioGroupv-model:value={this.radioRef}onUpdateValue={this.updateRadioTime}><div class={styles['crontab-list']}><NRadio value={'intervalTime'} /><div class={styles['crontab-list-item']}><div class={styles['item-text']}>{t(this.timeI18n!.every)}</div><div class={styles['number-input']}><NInputNumberdefaultValue={5}min={this.timeMin}max={this.timeMax}v-model:value={this.intervalPerformRef}onUpdateValue={this.onIntervalPerform}/></div><div class={styles['item-text']}>{t(this.timeI18n!.timeCarriedOut)}</div><div class={styles['number-input']}><NInputNumberdefaultValue={3}min={this.timeMin}max={this.timeMax}v-model:value={this.intervalStartRef}onUpdateValue={this.onIntervalStart}/></div><div class={styles['item-text']}>{t(this.timeI18n!.timeStart)}</div></div></div><div class={styles['crontab-list']}><NRadio value={'specificTime'} /><div class={styles['crontab-list-item']}><div>{t(this.timeI18n!.specificTime)}</div><div class={styles['select-input']}><NSelectmultipleoptions={specificList[this.timeSpecial]}placeholder={t(this.timeI18n!.specificTimeTip)}v-model:value={this.specificTimesRef}onUpdateValue={this.onSpecificTimes}/></div></div></div></NRadioGroup>)}
})

服务端

添加Crontab表达式检验(有两处:一处是新增Post接口、另一处是修改PUT接口),直接添加个检测方法供这两处调用:

        if (scheduleParam.getCrontab().startsWith("*")) {logger.error("The crontab must not start with *");putMsg(result, Status.CRONTAB_EVERY_SECOND_ERROR);return result;}

本文完!

本文由 白鲸开源科技 提供发布支持!

相关文章:

Apache DolphinScheduler 限制秒级别的定时调度

背景 Apache DolphinScheduler 定时任务配置采用的 7 位 Crontab 表达式&#xff0c;分别对应秒、分、时、月天、月、周天、年。 在团队日常开发工作中&#xff0c;工作流的定时调度一般不会细化到秒级别。但历史上出现过因配置的疏忽大意而产生故障时间&#xff0c;如应该配…...

Oracle 数据库创建用户并分配只读的权限

引言 在 Oracle 数据库的日常运维和开发过程中&#xff0c;用户管理是确保数据安全与访问控制的关键环节。通过合理创建用户并分配适当的权限&#xff0c;可以有效防止未授权的访问和操作。本文将详细介绍如何在 Oracle 数据库中&#xff1a; 创建新用户并设置复杂密码。授予…...

2个GitHub上最近比较火的Java开源项目

1. SpringBlade 微服务架构 标题 SpringBlade 微服务架构 摘要 SpringBlade 是一个由商业级项目升级优化而来的微服务架构&#xff0c;采用Spring Boot 3.2、Spring Cloud 2023等核心技术构建&#xff0c;遵循阿里巴巴编码规范&#xff0c;提供基于React和Vue的两个前端框架&am…...

【jvm】为什么要有GC

目录 1. 自动内存管理2. 提升程序稳定性3. 优化性能4. 跨平台能力5. 分代回收策略 1. 自动内存管理 1.JVM中的GC机制负责自动管理内存&#xff0c;这意味着开发人员不需要手动分配和释放内存。2.这一特性大大简化了Java程序的内存管理&#xff0c;降低了内存泄漏和内存溢出等问…...

【Rhino】【Python】根据contour创建地形mesh

将surface生成open curve封闭 #codingutf-8 import rhinoscriptsyntax as rs import mathdef adjust_endpoints():# 获取指定图层中的所有曲线all_objects rs.ObjectsByLayer("Level 19")if not all_objects:print("在Level 19图层中未找到对象")return#…...

蓝桥杯软件赛系列---lesson1

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 我们今天会再开一个系列&#xff0c;那就是蓝桥杯系列&#xff0c;我们会从最基础的开始讲起&#xff0c;大家想要备战明年蓝桥杯的&#xff0c;让我们一起加油。 工具安装 DevC…...

NanoLog起步笔记-1

nonolog起步笔记-1 背景与上下文写在前面Nanolog与一般的实时log的异同现代log的一般特性Nanolog的选择 背景与上下文 因为工作中用到了NanoLog。有必要研究一下。 前段时间研究了许多内容&#xff0c;以为写了比较详实的笔记&#xff0c;今天找了找&#xff0c;不仅笔记没找到…...

汽车车牌标记支持YOLO,COCO,VOC三种格式标记,4000张图片的数据集

本数据集支持YOLO&#xff0c;COCO&#xff0c;VOC三种格式标记汽车车牌&#xff0c;无论是新能源汽车还是油车都能识别标记&#xff0c;该数据集一共包含4000张图片 数据集分割 4000总图像数 训练组 70&#xff05; 2800图片 有效集 20&#xff05; 800图片 测…...

leetcode33.搜索旋转排序数组

整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], ..., nums[n-1], nums[0], nums[1], ..…...

Ansible自动化运维(三)playbook剧本详解

Ansible自动化运维这部分我将会分为五个部分来为大家讲解 &#xff08;一&#xff09;介绍、无密钥登录、安装部署、设置主机清单 &#xff08;二&#xff09;Ansible 中的 ad-hoc 模式 模块详解&#xff08;15&#xff09;个 &#xff08;三&#xff09;Playbook 模式详解 …...

通过PS和Unity制作2D动画之二:IK的使用

一、IK的概念 IK&#xff1a;Inverse Kinematics&#xff0c;反向动力学。 &#xff08;1&#xff09;正向动力学 在骨骼动画中&#xff0c;构建骨骼的方法被称为正向动力学。它的表现形式是&#xff1a;子骨骼&#xff08;关节&#xff09;的位置根据父骨骼&#xff08;关节…...

图像边缘检测原理和常用检测算子及MATLAB实现

一、边缘和边缘检测的概念 图像边缘是指图像中灰度值发生急剧变化的地方&#xff0c;这些变化通常对应于图像中物体的轮廓、边界或纹理的突变处。在数字图像处理中&#xff0c;边缘是图像的一个重要特征&#xff0c;它包含了关于物体形状、位置和大小等关键信息。 边缘检测是数…...

企业经营数据分析系统:提升决策能力的利器

搭建企业经营数据分析系统是当今企业绕不开的话题&#xff0c;企业想要在竞争激烈的市场当中突围而出&#xff0c;需要对于企业内部的各种数据了然于胸&#xff0c;同时对于外部的数据也有敏锐的把握能力&#xff0c;因此企业构建自身的经营性数据分析系统就显得尤其重要。作为…...

【49】AndroidStudio构建其他人开发的Android项目

(1)做Android软件开发&#xff0c;通常会看一些其他人开发的项目源码&#xff0c;当将这些项目的源码通过git clone到本地之后&#xff0c;用AndroidStudio进行打开时&#xff0c;通常会遇到一些环境配置的问题。本文即用来记录在构建他人开发项目源代码这一过程中遇到的一些常…...

Oracle 数据库中SERIALLY_REUSABLE包是一种特殊的包类型

1、SERIALLY_REUSABLE 包概述 在 Oracle 数据库中&#xff0c;SERIALLY_REUSABLE包是一种特殊的包类型。这种包的目的是为了更有效地利用内存&#xff0c;特别是在高并发环境下。当一个会话调用SERIALLY_REUSABLE包中的过程或函数时&#xff0c;该包的状态&#xff08;包括变量…...

css基础记录

基础 选择器 复合选择器 后代选择器 div p {}; 类似如上,找到div中所有的后代,注意是所有的后代 子代选择器 > div > a 只选择div的儿子中有a的 并集选择器 用逗号,分隔 p,div,span,h1 { … } 一般一行写一个 CSS元素显示模式 分为块元素,行内元素 块元素 特点…...

Python后端 -- 万字长文全面解析Django框架

自从2005年诞生以来&#xff0c;Django因其“开发速度快、安全性高”的特点迅速成为许多开发者的首选。无论是小型的个人项目&#xff0c;还是大型的企业应用&#xff0c;Django都能游刃有余地满足需求。我们将从Django的基础知识带你全面掌握Django&#xff0c;从基础知识到高…...

el-thee懒加载删除某条数据 ,el-thee懒加载重置,el-thee刷新某个节点

一、懒加载的tree已经全部展开&#xff0c;外部点击删除的时候不需要重新展开点击获取下一层数据 <template> <el-treeref"tree":data"treeData":props"defaultProps"render-after-expandhighlight-currentlazy:expand-on-click-node&q…...

【PyQt5教程 四】Qt Designer 样式表(styleSheet)实现基本小部件的自定义动态效果和资源浏览器背景添加方法

目录 一、成果演示&#xff1a; 二、样式表的使用方法: &#xff08;1&#xff09;样式表语法和属性&#xff1a; &#xff08;2&#xff09;样式表代码示例&#xff1a; &#xff08;3&#xff09;伪类和状态&#xff1a; &#xff08;4&#xff09;复合选择器&#xff…...

【git】--- 通过 git 和 gitolite 管理单仓库的 SDK

在编程的艺术世界里,代码和灵感需要寻找到最佳的交融点,才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。【git】--- 通过 git 和 gitolite 管理单仓库的 SDK 开发环境一、安装配置 gitolite二…...

CANN-HCCL-昇腾NPU分布式训练的通信库怎么选

8 卡 Atlas 800I A2 内部走 HCCS&#xff08;带宽 200GB/s&#xff09;&#xff0c;跨机走 RoCE&#xff08;带宽 100GB/s&#xff09;。HCCL 是昇腾NPU的通信库&#xff0c;对标 NVIDIA 的 NCCL。Tensor Parallel 和 Pipeline Parallel 的 All-Reduce、All-to-All 都靠它。 HC…...

瑞数6代JSVMP对抗实战:Node.js环境补全与412绕过

1. 这不是“绕过验证码”&#xff0c;而是一场Web前端对抗的深度解剖瑞数6代&#xff0c;业内常被称作“JSVMP黑盒”的典型代表——它不靠传统混淆堆砌代码体积&#xff0c;也不依赖简单的时间戳或行为采集做判断&#xff0c;而是把整个校验逻辑编译进一套自定义的、高度定制化…...

2026年AI写作辅助平台实测排行,哪款真正适合一站式撰稿?

2026 年学术 AI 论文工具已形成全流程、理工 / 社科、英文 / 中文、免费 / 付费的清晰分化。综合实测排行与场景适配&#xff0c;千笔AI 是中文全能首选&#xff0c;DeepSeek 学术版是理工开源首选&#xff0c;毕业之家是国内毕业专属首选。 一、2026 年实测排行 TOP5&#xff…...

java+vue+SpringBootjava+vue+SpringBoot中小型制造企业质量管理系统(程序+数据库+报告+部署教程+答辩指导)(程序+数据库+报告+部署教程+答辩指导)

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿ppt部署教程代码讲解代码时间修改工具 技术实现 开发语言&#xff1a;后端&#xff1a;Java 前端&#xff1a;vue框架&#xff1a;springboot数据库&#xff1a;mysql 开发工具 JDK版本&#xff1a;JDK1.8 数…...

Python之streamjam包语法、参数和实际应用案例

Python StreamJam 包完整使用指南 一、StreamJam 包核心概述 StreamJam 是 Python 中一款轻量级、高性能的流式数据处理工具包&#xff0c;专为实时数据流、增量数据处理、管道式数据转换、异步/同步流处理设计&#xff0c;核心定位是替代复杂的大数据框架&#xff08;如Spark、…...

内网离线部署RPA:打包EXE+本地激活+数据零上云方案

领导给了一周&#xff0c;我前三天全耗在这个报错上&#xff1a;无法连接到 activation.xxx.com 请检查网络连接后重试2024年5月&#xff0c;我用的蓝印RPA物理隔离内网部&#xff0c;处理核心业务数据&#xff0c;要求"数据不出本机&#xff0c;流程不外传&#xff0c;审…...

CANN-Profiler-昇腾NPU上推理慢到底慢在哪

推理服务上线前最重要的一步是性能 Profiling。ATB 的推理速度不达标&#xff0c;可能有十几个原因——不拿数据说话就是瞎猜。CANN Profiler 给你精确到每个 kernel 的执行时间。 开启 Profiling import torch_npu# 方法 1&#xff1a;Python API with torch_npu.profiler.pro…...

如何快速解决Windows 11区域模拟问题:完整API钩子技术指南

如何快速解决Windows 11区域模拟问题&#xff1a;完整API钩子技术指南 【免费下载链接】Locale_Remulator System Region and Language Simulator. 项目地址: https://gitcode.com/gh_mirrors/lo/Locale_Remulator Locale Remulator是一款强大的系统区域和语言模拟工具&…...

GQA:多查少算的 Attention 头组合

本文基于昇腾CANN和昇腾NPU&#xff0c;围绕 ops-transformer 仓库的相关技术展开。 MHA&#xff08;Multi-Head Attention&#xff09;每个 Head 一套 QKV——8 个 Head 就是 8 组。MQA 省过头了——8 个 Head 共享 K、V。GQA&#xff08;Grouped Query Attention&#xff09;…...

为什么你的AI搜索总不准?2026年5款高精度免费工具底层架构拆解:向量引擎、重排序模块与Query理解差异全曝光

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;为什么你的AI搜索总不准&#xff1f;——2026年免费高精度AI搜索工具全景洞察 AI搜索不准&#xff0c;根源常被误判为“模型不够大”&#xff0c;实则多源于查询理解失焦、上下文截断、知识新鲜度缺失与…...