ホームページ >ウェブフロントエンド >jsチュートリアル >Apache DolphinScheduler が第 2 レベルでタイミング スケジューリングを制限する

Apache DolphinScheduler が第 2 レベルでタイミング スケジューリングを制限する

Barbara Streisand
Barbara Streisandオリジナル
2024-12-22 14:55:13468ブラウズ

Apache DolphinScheduler Restricts Timing Scheduling at the Second Level

背景

Apache DolphinScheduler のタイミング タスク設定では、秒、分、時、日、月、曜日、年に対応する 7 桁の Crontab 式を使用します。

私たちのチームの日常的な開発作業では、通常、ワークフローのタイミング スケジューリングを第 2 レベルまで詳細に行う必要はありません。ただし、毎分実行されるべきワークフローが誤って毎秒実行されるように設定され、その結果、短期間に大量のワークフロー インスタンスが生成され、 Apache DolphinScheduler サービスとタスクが送信される Hadoop クラスターの可用性。

これに基づいて、チームは DolphinScheduler のタイミング タスク構成モジュールで Crontab 式を制限し、そのようなインシデントがプラットフォーム レベルで発生するのを防ぐことを決定しました。

解決

私たちの解決策は、フロントエンドとバックエンドの両方から Crontab 式の最初の位置を制限することです。

  • フロントエンド構成では「毎秒」オプションが提供されません
  • 最初の位置が *
  • の場合、サーバー側インターフェースはエラーを返します。

フロントエンドの変更

フロントエンド プロジェクトでは、秒、分、時間はすべて統合されたテンプレート (CrontabTime) であるため、新しいファイルが追加されます: dolphinscheduler-ui/src/components/crontab/modules/second.tsx

intervalTime と specificTime の 2 つのモードのみが保持されます

/*
 * 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 time
            const $interval = isStr($timeVal, '/')
            // Specific time
            const $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 times
            if ($interval) {
                radioRef.value = 'intervalTime'
                intervalStartRef.value = parseInt($interval[0])
                intervalPerformRef.value = parseInt($interval[1])
                timeRef.value = `${intervalStartRef.value}/${intervalPerformRef.value}`
                return
            }

            // Specific times
            if ($specific) {
                radioRef.value = 'specificTime'
                specificTimesRef.value = $specific.map((item) => parseInt(item))
                return
            }
        }

        // Interval start time(1)
        const onIntervalStart = (value: number | null) => {
            intervalStartRef.value = value || 0
            if (radioRef.value === 'intervalTime') {
                timeRef.value = `${intervalStartRef.value}/${intervalPerformRef.value}`
            }
        }

        // Interval execution time(2)
        const onIntervalPerform = (value: number | null) => {
            intervalPerformRef.value = value || 0
            if (radioRef.value === 'intervalTime') {
                timeRef.value = `${intervalStartRef.value}/${intervalPerformRef.value}`
            }
        }

        // Specific time
        const onSpecificTimes = (arr: Array<number>) => {
            specificTimesRef.value = arr
            if (radioRef.value === 'specificTime') {
                specificReset()
            }
        }

        // Reset interval time
        const intervalReset = () => {
            timeRef.value = `${intervalStartRef.value}/${intervalPerformRef.value}`
        }

        // Reset specific time
        const specificReset = () => {
            let timeValue = '0'
            if (specificTimesRef.value.length) {
                timeValue = specificTimesRef.value.join(',')
            }
            timeRef.value = timeValue
        }

        const updateRadioTime = (value: string) => {
            switch (value) {
                case 'intervalTime':
                    intervalReset()
                    break
                case '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 (
            <NRadioGroup
                v-model:value={this.radioRef}
                onUpdateValue={this.updateRadioTime}
            >
                <div>



<h3>
  
  
  Server-side
</h3>

<p>Add Crontab expression validation (there are two places: one is the new POST interface, and the other is the modified PUT interface), directly add a validation method for these two places to call:<br>
</p>

<pre class="brush:php;toolbar:false">        if (scheduleParam.getCrontab().startsWith("*")) {
            logger.error("The crontab must not start with *");
            putMsg(result, Status.CRONTAB_EVERY_SECOND_ERROR);
            return result;
        }

これで記事は終わりです。

以上がApache DolphinScheduler が第 2 レベルでタイミング スケジューリングを制限するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。