/** * Licensed 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. */ package org.apache.aurora.scheduler.scheduling; import javax.inject.Singleton; import com.google.common.util.concurrent.RateLimiter; import com.google.inject.AbstractModule; import com.google.inject.PrivateModule; import com.google.inject.TypeLiteral; import org.apache.aurora.common.args.Arg; import org.apache.aurora.common.args.CmdLine; import org.apache.aurora.common.args.constraints.Positive; import org.apache.aurora.common.quantity.Amount; import org.apache.aurora.common.quantity.Time; import org.apache.aurora.common.util.TruncatedBinaryBackoff; import org.apache.aurora.scheduler.base.TaskGroupKey; import org.apache.aurora.scheduler.events.PubsubEventModule; import org.apache.aurora.scheduler.preemptor.BiCache; import org.apache.aurora.scheduler.scheduling.RescheduleCalculator.RescheduleCalculatorImpl; import static org.apache.aurora.scheduler.SchedulerServicesModule.addSchedulerActiveServiceBinding; /** * Binding module for task scheduling logic. */ public class SchedulingModule extends AbstractModule { @CmdLine(name = "max_schedule_attempts_per_sec", help = "Maximum number of scheduling attempts to make per second.") private static final Arg<Double> MAX_SCHEDULE_ATTEMPTS_PER_SEC = Arg.create(40D); @CmdLine(name = "flapping_task_threshold", help = "A task that repeatedly runs for less than this time is considered to be flapping.") private static final Arg<Amount<Long, Time>> FLAPPING_THRESHOLD = Arg.create(Amount.of(5L, Time.MINUTES)); @CmdLine(name = "initial_flapping_task_delay", help = "Initial amount of time to wait before attempting to schedule a flapping task.") private static final Arg<Amount<Long, Time>> INITIAL_FLAPPING_DELAY = Arg.create(Amount.of(30L, Time.SECONDS)); @CmdLine(name = "max_flapping_task_delay", help = "Maximum delay between attempts to schedule a flapping task.") private static final Arg<Amount<Long, Time>> MAX_FLAPPING_DELAY = Arg.create(Amount.of(5L, Time.MINUTES)); @CmdLine(name = "max_reschedule_task_delay_on_startup", help = "Upper bound of random delay for pending task rescheduling on scheduler startup.") private static final Arg<Amount<Integer, Time>> MAX_RESCHEDULING_DELAY = Arg.create(Amount.of(30, Time.SECONDS)); @Positive @CmdLine(name = "first_schedule_delay", help = "Initial amount of time to wait before first attempting to schedule a PENDING task.") private static final Arg<Amount<Long, Time>> FIRST_SCHEDULE_DELAY = Arg.create(Amount.of(1L, Time.MILLISECONDS)); @Positive @CmdLine(name = "initial_schedule_penalty", help = "Initial amount of time to wait before attempting to schedule a task that has failed" + " to schedule.") private static final Arg<Amount<Long, Time>> INITIAL_SCHEDULE_PENALTY = Arg.create(Amount.of(1L, Time.SECONDS)); @CmdLine(name = "max_schedule_penalty", help = "Maximum delay between attempts to schedule a PENDING tasks.") private static final Arg<Amount<Long, Time>> MAX_SCHEDULE_PENALTY = Arg.create(Amount.of(1L, Time.MINUTES)); @CmdLine(name = "offer_reservation_duration", help = "Time to reserve a agent's offers while " + "trying to satisfy a task preempting another.") private static final Arg<Amount<Long, Time>> RESERVATION_DURATION = Arg.create(Amount.of(3L, Time.MINUTES)); @Positive @CmdLine(name = "scheduling_max_batch_size", help = "The maximum number of scheduling attempts that can be processed in a batch.") private static final Arg<Integer> SCHEDULING_MAX_BATCH_SIZE = Arg.create(3); @Positive @CmdLine(name = "max_tasks_per_schedule_attempt", help = "The maximum number of tasks to pick in a single scheduling attempt.") private static final Arg<Integer> MAX_TASKS_PER_SCHEDULE_ATTEMPT = Arg.create(5); @Override protected void configure() { install(new PrivateModule() { @Override protected void configure() { bind(TaskGroups.TaskGroupsSettings.class).toInstance(new TaskGroups.TaskGroupsSettings( FIRST_SCHEDULE_DELAY.get(), new TruncatedBinaryBackoff( INITIAL_SCHEDULE_PENALTY.get(), MAX_SCHEDULE_PENALTY.get()), RateLimiter.create(MAX_SCHEDULE_ATTEMPTS_PER_SEC.get()), MAX_TASKS_PER_SCHEDULE_ATTEMPT.get())); bind(RescheduleCalculatorImpl.RescheduleCalculatorSettings.class) .toInstance(new RescheduleCalculatorImpl.RescheduleCalculatorSettings( new TruncatedBinaryBackoff(INITIAL_FLAPPING_DELAY.get(), MAX_FLAPPING_DELAY.get()), FLAPPING_THRESHOLD.get(), MAX_RESCHEDULING_DELAY.get())); bind(RescheduleCalculator.class).to(RescheduleCalculatorImpl.class).in(Singleton.class); expose(RescheduleCalculator.class); bind(TaskGroups.class).in(Singleton.class); expose(TaskGroups.class); } }); PubsubEventModule.bindSubscriber(binder(), TaskGroups.class); bind(new TypeLiteral<Integer>() { }) .annotatedWith(TaskGroups.SchedulingMaxBatchSize.class) .toInstance(SCHEDULING_MAX_BATCH_SIZE.get()); bind(TaskGroups.TaskGroupBatchWorker.class).in(Singleton.class); addSchedulerActiveServiceBinding(binder()).to(TaskGroups.TaskGroupBatchWorker.class); install(new PrivateModule() { @Override protected void configure() { bind(new TypeLiteral<BiCache<String, TaskGroupKey>>() { }).in(Singleton.class); bind(BiCache.BiCacheSettings.class).toInstance( new BiCache.BiCacheSettings(RESERVATION_DURATION.get(), "reservation")); bind(TaskScheduler.class).to(TaskScheduler.TaskSchedulerImpl.class); bind(TaskScheduler.TaskSchedulerImpl.class).in(Singleton.class); expose(TaskScheduler.class); } }); PubsubEventModule.bindSubscriber(binder(), TaskScheduler.class); install(new PrivateModule() { @Override protected void configure() { bind(TaskThrottler.class).in(Singleton.class); expose(TaskThrottler.class); } }); PubsubEventModule.bindSubscriber(binder(), TaskThrottler.class); } }