Repository: stratos Updated Branches: refs/heads/master d41adfad0 -> e2f628cb9
Adding dependent-scaling.drl file for handling scaling based on dependency Project: http://git-wip-us.apache.org/repos/asf/stratos/repo Commit: http://git-wip-us.apache.org/repos/asf/stratos/commit/e2f628cb Tree: http://git-wip-us.apache.org/repos/asf/stratos/tree/e2f628cb Diff: http://git-wip-us.apache.org/repos/asf/stratos/diff/e2f628cb Branch: refs/heads/master Commit: e2f628cb9b0d2c90382bdde9e9f3427af403c388 Parents: d41adfa Author: Lahiru Sandaruwan <[email protected]> Authored: Thu Nov 27 13:00:55 2014 +0530 Committer: Lahiru Sandaruwan <[email protected]> Committed: Thu Nov 27 13:00:55 2014 +0530 ---------------------------------------------------------------------- .../monitor/cluster/AbstractClusterMonitor.java | 11 ++ .../cluster/VMServiceClusterMonitor.java | 11 +- .../rule/AutoscalerRuleEvaluator.java | 14 ++ .../src/main/conf/drools/dependent-scaling.drl | 153 +++++++++++++++++++ 4 files changed, 188 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/stratos/blob/e2f628cb/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/cluster/AbstractClusterMonitor.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/cluster/AbstractClusterMonitor.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/cluster/AbstractClusterMonitor.java index ba061a2..e165360 100644 --- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/cluster/AbstractClusterMonitor.java +++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/cluster/AbstractClusterMonitor.java @@ -57,6 +57,7 @@ public abstract class AbstractClusterMonitor extends Monitor implements Runnable protected FactHandle minCheckFactHandle; protected FactHandle obsoleteCheckFactHandle; protected FactHandle scaleCheckFactHandle; + protected FactHandle dependentScaleCheckFactHandle; protected boolean hasFaultyMember = false; protected boolean stop = false; private AtomicBoolean monitoringStarted; @@ -68,6 +69,7 @@ public abstract class AbstractClusterMonitor extends Monitor implements Runnable private StatefulKnowledgeSession minCheckKnowledgeSession; private StatefulKnowledgeSession obsoleteCheckKnowledgeSession; private StatefulKnowledgeSession scaleCheckKnowledgeSession; + private StatefulKnowledgeSession dependentScaleCheckKnowledgeSession; private boolean isDestroyed; private AutoscalerRuleEvaluator autoscalerRuleEvaluator; protected String serviceType; @@ -84,6 +86,7 @@ public abstract class AbstractClusterMonitor extends Monitor implements Runnable this.obsoleteCheckKnowledgeSession = autoscalerRuleEvaluator.getObsoleteCheckStatefulSession(); this.scaleCheckKnowledgeSession = autoscalerRuleEvaluator.getScaleCheckStatefulSession(); this.minCheckKnowledgeSession = autoscalerRuleEvaluator.getMinCheckStatefulSession(); + this.dependentScaleCheckKnowledgeSession = autoscalerRuleEvaluator.getMinCheckStatefulSession(); this.status = ClusterStatus.Created; } @@ -397,4 +400,12 @@ public abstract class AbstractClusterMonitor extends Monitor implements Runnable public void setMonitoringStarted(boolean monitoringStarted) { this.monitoringStarted.set(monitoringStarted); } + + public StatefulKnowledgeSession getDependentScaleCheckKnowledgeSession() { + return dependentScaleCheckKnowledgeSession; + } + + public void setDependentScaleCheckKnowledgeSession(StatefulKnowledgeSession dependentScaleCheckKnowledgeSession) { + this.dependentScaleCheckKnowledgeSession = dependentScaleCheckKnowledgeSession; + } } http://git-wip-us.apache.org/repos/asf/stratos/blob/e2f628cb/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/cluster/VMServiceClusterMonitor.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/cluster/VMServiceClusterMonitor.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/cluster/VMServiceClusterMonitor.java index 0bf583a..6fcafea 100644 --- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/cluster/VMServiceClusterMonitor.java +++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/cluster/VMServiceClusterMonitor.java @@ -292,7 +292,16 @@ public class VMServiceClusterMonitor extends VMClusterMonitor { float requiredInstanceCount = networkPartitionContext.getMinInstanceCount() * scalingFactorBasedOnDependencies; int roundedRequiredInstanceCount = getRoundedInstanceCount(requiredInstanceCount, vmClusterContext.getAutoscalePolicy().getInstanceRoundingFactor()); - networkPartitionContext.setRequiredInstanceCountBasedOnStats(roundedRequiredInstanceCount); + networkPartitionContext.setRequiredInstanceCountBasedOnDependencies(roundedRequiredInstanceCount); + + getDependentScaleCheckKnowledgeSession().setGlobal("clusterId", getClusterId()); + getDependentScaleCheckKnowledgeSession().setGlobal("scalingFactor", scalingFactorBasedOnDependencies); + getDependentScaleCheckKnowledgeSession().setGlobal("instanceRoundingFactor", + vmClusterContext.getAutoscalePolicy().getInstanceRoundingFactor()); + + dependentScaleCheckFactHandle = AutoscalerRuleEvaluator.evaluateScaleCheck(getScaleCheckKnowledgeSession() + , scaleCheckFactHandle, networkPartitionContext); + } public void sendClusterScalingEvent(String networkPartitionId, float factor) { http://git-wip-us.apache.org/repos/asf/stratos/blob/e2f628cb/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/rule/AutoscalerRuleEvaluator.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/rule/AutoscalerRuleEvaluator.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/rule/AutoscalerRuleEvaluator.java index a66345a..15894ef 100644 --- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/rule/AutoscalerRuleEvaluator.java +++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/rule/AutoscalerRuleEvaluator.java @@ -138,6 +138,20 @@ public class AutoscalerRuleEvaluator { return handle; } + public static FactHandle evaluateDependentScaleCheck(StatefulKnowledgeSession ksession, FactHandle handle, Object obj) { + if (handle == null) { + ksession.setGlobal("$delegator", new RuleTasksDelegator()); + handle = ksession.insert(obj); + } else { + ksession.update(handle, obj); + } + ksession.fireAllRules(); + if(log.isDebugEnabled()){ + log.debug(String.format("Dependent scale check executed for : %s ", obj)); + } + return handle; + } + public static FactHandle evaluateTerminateAll(StatefulKnowledgeSession ksession, FactHandle handle, Object obj) { if (handle == null) { ksession.setGlobal("$delegator", new RuleTasksDelegator()); http://git-wip-us.apache.org/repos/asf/stratos/blob/e2f628cb/products/stratos/modules/distribution/src/main/conf/drools/dependent-scaling.drl ---------------------------------------------------------------------- diff --git a/products/stratos/modules/distribution/src/main/conf/drools/dependent-scaling.drl b/products/stratos/modules/distribution/src/main/conf/drools/dependent-scaling.drl new file mode 100644 index 0000000..6a1300e --- /dev/null +++ b/products/stratos/modules/distribution/src/main/conf/drools/dependent-scaling.drl @@ -0,0 +1,153 @@ +/* + * 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. + */ + +package org.apache.stratos.autoscaler.rule; + +import org.apache.stratos.messaging.domain.topology.Service; +import org.apache.stratos.messaging.domain.topology.Cluster; +import org.apache.stratos.autoscaler.AutoscalerContext; +import org.apache.stratos.autoscaler.MemberStatsContext; +import org.apache.stratos.autoscaler.Constants; +import org.apache.stratos.autoscaler.NetworkPartitionContext; +import org.apache.stratos.autoscaler.policy.PolicyManager; +import org.apache.stratos.autoscaler.policy.model.AutoscalePolicy; +import org.apache.stratos.autoscaler.client.CloudControllerClient; +import org.apache.stratos.autoscaler.algorithm.AutoscaleAlgorithm; +import org.apache.stratos.autoscaler.algorithm.OneAfterAnother; +import org.apache.stratos.autoscaler.algorithm.RoundRobin; +import org.apache.stratos.autoscaler.PartitionContext; +import org.apache.stratos.autoscaler.rule.AutoscalerRuleEvaluator; +import org.apache.stratos.autoscaler.partition.PartitionGroup; +import org.apache.stratos.cloud.controller.stub.deployment.partition.Partition; +import org.apache.stratos.cloud.controller.stub.pojo.MemberContext; + +import org.apache.stratos.autoscaler.policy.model.LoadAverage +import org.apache.stratos.autoscaler.policy.model.MemoryConsumption + +global org.apache.stratos.autoscaler.rule.RuleLog log; +global org.apache.stratos.autoscaler.rule.RuleTasksDelegator $delegator; +global org.apache.stratos.autoscaler.policy.model.AutoscalePolicy autoscalePolicy; +global java.lang.String clusterId; +global java.lang.String instanceId; +global java.lang.Float laReset; +global java.lang.Float numberOfRequiredInstances; +global java.lang.Boolean isPrimary; +global java.lang.String lbRef; +global java.util.List primaryMembers; + +rule "Dependent Scaling Rule" +dialect "mvel" + when + + networkPartitionContext : NetworkPartitionContext () + algorithmName : String() from networkPartitionContext.getPartitionAlgorithm(); + autoscaleAlgorithm : AutoscaleAlgorithm() from $delegator.getAutoscaleAlgorithm(algorithmName) + + roundedRequiredInstanceCount : Integer() from networkPartitionContext.getRequiredInstanceCountBasedOnDependencies(); + activeInstancesCount : Integer() from $delegator.getMemberCount(clusterId , 0); + + scaleUp : Boolean() from (activeInstancesCount < roundedRequiredInstanceCount ) + scaleDown : Boolean() from (activeInstancesCount > roundedRequiredInstanceCount ) + + eval(log.debug("[dependent-scaling] " + " [cluster] " + clusterId + " Scale-up action: " + scaleUp)) + eval(log.debug("[dependent-scaling] " + " [cluster] " + clusterId + " Scale-down action: " + scaleDown)) + + then + + if(scaleUp){ + + int additionalInstances = roundedRequiredInstanceCount - activeInstancesCount ; + int count = 0; + while(count != additionalInstances){ + Partition partition = autoscaleAlgorithm.getNextScaleUpPartition(networkPartitionContext, clusterId); + if(partition != null){ + log.info("[scale-up] Partition available, hence trying to spawn an instance to scale up!" ); + log.debug("[scale-up] " + " [partition] " + partition.getId() + " [cluster] " + clusterId ); + $delegator.delegateSpawn(networkPartitionContext.getPartitionCtxt(partition.getId()), clusterId, instanceId, lbRef, isPrimary); + count++; + } + } + } else if(scaleDown){ + + log.debug("[scale-down] Decided to Scale down [cluster] " + clusterId); + + MemberStatsContext selectedMemberStatsContext = null; + double lowestOverallLoad = 0.0; + boolean foundAValue = false; + Partition partition = autoscaleAlgorithm.getNextScaleDownPartition(networkPartitionContext, clusterId); + if(partition != null){ + log.info("[scale-down] Partition available to scale down "); + log.debug("[scale-down] " + " [partition] " + partition.getId() + " [cluster] " + clusterId); + partitionContext = networkPartitionContext.getPartitionCtxt(partition.getId()); + + + // In partition context member stat context, all the primary members need to be + // avoided being selected as the member to terminated + + for(MemberStatsContext memberStatsContext: partitionContext.getMemberStatsContexts().values()){ + + if( !primaryMembers.contains(memberStatsContext.getMemberId()) ) { + + LoadAverage loadAverage = memberStatsContext.getLoadAverage(); + log.debug("[scale-down] " + " [cluster] " + + clusterId + " [member] " + memberStatsContext.getMemberId() + " Load average: " + loadAverage); + + MemoryConsumption memoryConsumption = memberStatsContext.getMemoryConsumption(); + log.debug("[scale-down] " + " [partition] " + partition.getId() + " [cluster] " + + clusterId + " [member] " + memberStatsContext.getMemberId() + " Memory consumption: " + memoryConsumption); + + double predictedCpu = $delegator.getPredictedValueForNextMinute(loadAverage.getAverage(),loadAverage.getGradient(),loadAverage.getSecondDerivative(), 1); + log.debug("[scale-down] " + " [partition] " + partition.getId() + " [cluster] " + + clusterId + " [member] " + memberStatsContext.getMemberId() + " Predicted CPU: " + predictedCpu); + + double predictedMemoryConsumption = $delegator.getPredictedValueForNextMinute(memoryConsumption.getAverage(),memoryConsumption.getGradient(),memoryConsumption.getSecondDerivative(), 1); + log.debug("[scale-down] " + " [partition] " + partition.getId() + " [cluster] " + + clusterId + " [member] " + memberStatsContext.getMemberId() + " Predicted memory consumption: " + predictedMemoryConsumption); + + double overallLoad = (predictedCpu + predictedMemoryConsumption) / 2; + log.debug("[scale-down] " + " [partition] " + partition.getId() + " [cluster] " + + clusterId + " [member] " + memberStatsContext.getMemberId() + " Overall load: " + overallLoad); + + if(!foundAValue){ + foundAValue = true; + selectedMemberStatsContext = memberStatsContext; + lowestOverallLoad = overallLoad; + } else if(overallLoad < lowestOverallLoad){ + selectedMemberStatsContext = memberStatsContext; + lowestOverallLoad = overallLoad; + } + } + } + if(selectedMemberStatsContext != null) { + log.info("[scale-down] Trying to terminating an instance to scale down!" ); + log.debug("[scale-down] " + " [partition] " + partition.getId() + " [cluster] " + + clusterId + " Member with lowest overall load: " + selectedMemberStatsContext.getMemberId()); + + $delegator.delegateTerminate(partitionContext, selectedMemberStatsContext.getMemberId()); + } + } + } else{ + + } + +end + + + +
