support for scale down in group wise and application wise
Project: http://git-wip-us.apache.org/repos/asf/stratos/repo Commit: http://git-wip-us.apache.org/repos/asf/stratos/commit/22f46e07 Tree: http://git-wip-us.apache.org/repos/asf/stratos/tree/22f46e07 Diff: http://git-wip-us.apache.org/repos/asf/stratos/diff/22f46e07 Branch: refs/heads/master Commit: 22f46e079d61af35aca392b1071452783521d1b6 Parents: 8742bac Author: reka <[email protected]> Authored: Mon Dec 22 15:45:47 2014 +0530 Committer: reka <[email protected]> Committed: Mon Dec 22 17:45:22 2014 +0530 ---------------------------------------------------------------------- .../applications/topic/ApplicationBuilder.java | 49 +++- .../monitor/component/ApplicationMonitor.java | 89 +++--- .../monitor/component/GroupMonitor.java | 276 ++++++++++--------- .../component/ParentComponentMonitor.java | 10 +- 4 files changed, 243 insertions(+), 181 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/stratos/blob/22f46e07/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/applications/topic/ApplicationBuilder.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/applications/topic/ApplicationBuilder.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/applications/topic/ApplicationBuilder.java index 74f63f8..0325a02 100644 --- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/applications/topic/ApplicationBuilder.java +++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/applications/topic/ApplicationBuilder.java @@ -188,6 +188,37 @@ public class ApplicationBuilder { } } + public static void handleApplicationInstanceTerminatingEvent(String appId, String instanceId) { + if (log.isDebugEnabled()) { + log.debug("Handling application Terminating event: [application-id] " + appId + + " [instance] " + instanceId); + } + + Applications applications = ApplicationHolder.getApplications(); + Application application = applications.getApplication(appId); + //update the status of the Group + if (application == null) { + log.warn(String.format("Application does not exist: [application-id] %s", + appId)); + return; + } + + ApplicationStatus status = ApplicationStatus.Terminating; + ApplicationInstance applicationInstance = application.getInstanceContexts(instanceId); + if (applicationInstance.isStateTransitionValid(status)) { + //setting the status, persist and publish + application.setStatus(status, instanceId); + updateApplicationMonitor(appId, status, applicationInstance.getNetworkPartitionId(), + instanceId); + ApplicationHolder.persistApplication(application); + ApplicationsEventPublisher.sendApplicationInstanceInactivatedEvent(appId, instanceId); + } else { + log.warn(String.format("Application state transition is not valid: [application-id] %s " + + " [instance-id] %s [current-status] %s [status-requested] %s", + appId, instanceId, applicationInstance.getStatus(), status)); + } + } + public static void handleApplicationRemoval(String appId) { if (log.isDebugEnabled()) { log.debug("Handling application unDeployment for [application-id] " + appId); @@ -316,21 +347,9 @@ public class ApplicationBuilder { clusterData = application.getClusterDataRecursively(); Collection<ApplicationInstance> applicationInstances = application. getInstanceIdToInstanceContextMap().values(); - ApplicationStatus status = ApplicationStatus.Terminating; - for (ApplicationInstance applicationInstance : applicationInstances) { - if (applicationInstance.isStateTransitionValid(status)) { - //setting the status, persist and publish - application.setStatus(status, applicationInstance.getInstanceId()); - updateApplicationMonitor(applicationId, status, applicationInstance.getNetworkPartitionId(), - applicationInstance.getInstanceId()); - ApplicationHolder.persistApplication(application); - ApplicationsEventPublisher.sendApplicationInstanceTerminatingEvent(applicationId, - applicationInstance.getInstanceId()); - } else { - log.warn(String.format("Application Instance state transition is not valid: [application-id] %s " + - " [instance-id] %s [current-status] %s [status-requested] %s", applicationId, - applicationInstance.getInstanceId() + applicationInstance.getStatus(), status)); - } + + for (ApplicationInstance instance : applicationInstances) { + handleApplicationInstanceTerminatingEvent(applicationId, instance.getInstanceId()); } } finally { ApplicationHolder.releaseWriteLock(); http://git-wip-us.apache.org/repos/asf/stratos/blob/22f46e07/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/ApplicationMonitor.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/ApplicationMonitor.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/ApplicationMonitor.java index f9dcf56..89b452f 100644 --- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/ApplicationMonitor.java +++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/ApplicationMonitor.java @@ -95,32 +95,16 @@ public class ApplicationMonitor extends ParentComponentMonitor { if (instance.getStatus().getCode() <= GroupStatus.Active.getCode()) { //Gives priority to scaling max out rather than dependency scaling if (!instanceContext.getIdToScalingOverMaxEvent().isEmpty()) { - if(networkPartitionContext.getPendingInstancesCount() == 0) { - //handling the application bursting only when there are no pending instances found - try { - if (log.isInfoEnabled()) { - log.info("Handling application busting, " + - "since resources are exhausted in " + - "this application instance "); - } - createInstanceOnBurstingForApplication(); - } catch (TopologyInConsistentException e) { - log.error("Error while bursting the application", e); - } catch (PolicyValidationException e) { - log.error("Error while bursting the application", e); - } catch (MonitorNotFoundException e) { - log.error("Error while bursting the application", e); - } - } else { - if(log.isDebugEnabled()) { - log.debug("Pending Application instance found. " + - "Hence waiting for it to become active"); - } - } - - } else { + //handling the scaling max out of the children + handleScalingMaxOut(networkPartitionContext); + + } else if(!instanceContext.getIdToScalingEvent().isEmpty()) { + //handling the dependent scaling for application handleDependentScaling(instanceContext, networkPartitionContext); + } else if(!instanceContext.getIdToScalingDownBeyondMinEvent().isEmpty()) { + //handling the scale down of the application + handleScalingDownBeyondMin(instanceContext, networkPartitionContext); } } } @@ -130,15 +114,58 @@ public class ApplicationMonitor extends ParentComponentMonitor { monitoringRunnable.run(); } - @Override - public void onChildScalingDownBeyondMinEvent(ScalingDownBeyondMinEvent scalingDownBeyondMinEvent) { + private void handleScalingMaxOut(NetworkPartitionContext networkPartitionContext) { + if (networkPartitionContext.getPendingInstancesCount() == 0) { + //handling the application bursting only when there are no pending instances found + try { + if (log.isInfoEnabled()) { + log.info("Handling application busting, " + + "since resources are exhausted in " + + "this application instance "); + } + handleApplicationBursting(); + } catch (TopologyInConsistentException e) { + log.error("Error while bursting the application", e); + } catch (PolicyValidationException e) { + log.error("Error while bursting the application", e); + } catch (MonitorNotFoundException e) { + log.error("Error while bursting the application", e); + } + } else { + if (log.isDebugEnabled()) { + log.debug("Pending Application instance found. " + + "Hence waiting for it to become active"); + } + } + } + + private void handleScalingDownBeyondMin(InstanceContext instanceContext, + NetworkPartitionContext nwPartitionContext) { + //Traverse through all the children to see whether all have sent the scale down + boolean allChildrenScaleDown = false; + for (Monitor monitor : this.aliasToActiveMonitorsMap.values()) { + if (instanceContext.getScalingDownBeyondMinEvent(monitor.getId()) == null) { + allChildrenScaleDown = false; + break; + } else { + allChildrenScaleDown = true; + } + } + + //all the children sent the scale down only, it will try to scale down + if (allChildrenScaleDown) { + //Check whether this app monitor has bursted application + ApplicationBuilder.handleApplicationInstanceTerminatingEvent(this.appId, + instanceContext.getId()); + } + + //Resetting the events + instanceContext.setIdToScalingDownBeyondMinEvent( + new HashMap<String, ScalingDownBeyondMinEvent>()); - String networkPartitionId = scalingDownBeyondMinEvent.getNetworkPartitionId(); - String instanceId = scalingDownBeyondMinEvent.getInstanceId(); - getNetworkPartitionContext(networkPartitionId).getInstanceContext(instanceId). - addScalingDownBeyondMinEvent(scalingDownBeyondMinEvent); } + /** * Find the group monitor by traversing recursively in the hierarchical monitors. * @@ -325,7 +352,7 @@ public class ApplicationMonitor extends ParentComponentMonitor { return instanceId; } - public void createInstanceOnBurstingForApplication() throws TopologyInConsistentException, + public void handleApplicationBursting() throws TopologyInConsistentException, PolicyValidationException, MonitorNotFoundException { Application application = ApplicationHolder.getApplications().getApplication(appId); http://git-wip-us.apache.org/repos/asf/stratos/blob/22f46e07/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/GroupMonitor.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/GroupMonitor.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/GroupMonitor.java index 33ade21..c8a59cf 100644 --- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/GroupMonitor.java +++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/GroupMonitor.java @@ -33,7 +33,6 @@ import org.apache.stratos.autoscaler.exception.application.DependencyBuilderExce import org.apache.stratos.autoscaler.exception.application.MonitorNotFoundException; import org.apache.stratos.autoscaler.exception.application.TopologyInConsistentException; import org.apache.stratos.autoscaler.monitor.Monitor; -import org.apache.stratos.autoscaler.monitor.cluster.ClusterMonitor; import org.apache.stratos.autoscaler.monitor.events.*; import org.apache.stratos.autoscaler.monitor.events.builder.MonitorStatusEventBuilder; import org.apache.stratos.autoscaler.pojo.policy.PolicyManager; @@ -41,13 +40,19 @@ import org.apache.stratos.autoscaler.pojo.policy.deployment.ChildPolicy; import org.apache.stratos.autoscaler.pojo.policy.deployment.partition.network.ChildLevelNetworkPartition; import org.apache.stratos.autoscaler.pojo.policy.deployment.partition.network.ChildLevelPartition; import org.apache.stratos.autoscaler.util.ServiceReferenceHolder; -import org.apache.stratos.messaging.domain.applications.*; +import org.apache.stratos.messaging.domain.applications.Application; +import org.apache.stratos.messaging.domain.applications.ApplicationStatus; +import org.apache.stratos.messaging.domain.applications.Group; +import org.apache.stratos.messaging.domain.applications.GroupStatus; import org.apache.stratos.messaging.domain.instance.GroupInstance; import org.apache.stratos.messaging.domain.instance.Instance; import org.apache.stratos.messaging.domain.topology.ClusterStatus; import org.apache.stratos.messaging.domain.topology.lifecycle.LifeCycleState; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; /** * This is GroupMonitor to monitor the group which consists of @@ -106,111 +111,158 @@ public class GroupMonitor extends ParentComponentMonitor { if (instance.getStatus().getCode() <= GroupStatus.Active.getCode()) { //Gives priority to scaling max out rather than dependency scaling if (!instanceContext.getIdToScalingOverMaxEvent().isEmpty()) { - if(!hasScalingDependents) { - //handling the group scaling and if pending instances found, - // reject the max - if (groupScalingEnabled) { - if(networkPartitionContext.getPendingInstancesCount() == 0) { - //one of the child is loaded and max out. - // Hence creating new group instance - if(log.isDebugEnabled()) { - log.debug("Handling group scaling for the [group] " + id + - "upon a max out event from " + - "the children"); - } - boolean createOnDemand = createInstanceOnDemand(instanceContext. - getParentInstanceId()); - if (!createOnDemand) { - //couldn't create new instance. Hence notifying the parent - MonitorStatusEventBuilder.handleScalingOverMaxEvent(parent, - networkPartitionContext.getId(), - instanceContext.getParentInstanceId(), - appId); - } - } else { - if(log.isDebugEnabled()) { - log.debug("Pending Group instance found. " + - "Hence waiting for it to become active"); - } - } - - } else { - //notifying the parent if no group scaling enabled here - MonitorStatusEventBuilder.handleScalingOverMaxEvent(parent, - networkPartitionContext.getId(), - instanceContext.getParentInstanceId(), - appId); - } - } else { - //has scaling dependents. Should notify the parent - if(log.isDebugEnabled()) { - log.debug("This [Group] " + id + " [scale-up] dependencies. " + - "Hence notifying the [parent] " + parent.getId() ); - } - //notifying the parent when scale dependents found - int maxInstances = ((GroupLevelNetworkPartitionContext) - networkPartitionContext).getMaxInstanceCount(); - if(groupScalingEnabled && maxInstances > networkPartitionContext. - getNonTerminatedInstancesCount()) { - //increase group by one more instance - float minInstances = ((GroupLevelNetworkPartitionContext) - networkPartitionContext).getMinInstanceCount(); - - float factor = (minInstances + 1)/minInstances; - MonitorStatusEventBuilder. - handleClusterScalingEvent(parent, - networkPartitionContext.getId(), - instanceContext.getParentInstanceId(), - factor, id); - } else { - MonitorStatusEventBuilder.handleScalingOverMaxEvent(parent, - networkPartitionContext.getId(), - instanceContext.getParentInstanceId(), - id); - } - } - //Resetting the max events - instanceContext.setIdToScalingOverMaxEvent( - new HashMap<String, ScalingUpBeyondMaxEvent>()); - } else if(!instanceContext.getIdToScalingDownBeyondMinEvent().isEmpty()){ - - handleScalingDownBeyondMin(instanceContext, networkPartitionContext); - } else { + //handling the max out of the children + handleScalingMaxOut(networkPartitionContext, instanceContext); + } else if (!instanceContext.getIdToScalingEvent().isEmpty()) { + //handling the dependent scaling handleDependentScaling(instanceContext, networkPartitionContext); + + } else if (!instanceContext.getIdToScalingDownBeyondMinEvent().isEmpty()) { + //scale down only when extra instances found + handleScalingDownBeyondMin(instanceContext, networkPartitionContext); } } - - } - - } } }; monitoringRunnable.run(); } - @Override - public void onChildScalingDownBeyondMinEvent(ScalingDownBeyondMinEvent scalingDownBeyondMinEvent) { + private void handleScalingMaxOut(NetworkPartitionContext networkPartitionContext, + InstanceContext instanceContext) { + if (!hasScalingDependents) { + //handling the group scaling and if pending instances found, + // reject the max + createGroupInstanceOnScaling(networkPartitionContext, + instanceContext.getParentInstanceId()); + } else { + notifyParentOnMaxOut(networkPartitionContext, instanceContext); + } + //Resetting the max events + instanceContext.setIdToScalingOverMaxEvent( + new HashMap<String, ScalingUpBeyondMaxEvent>()); + } + + private void handleScalingDownBeyondMin(InstanceContext instanceContext, + NetworkPartitionContext nwPartitionContext) { + //Traverse through all the children to see whether all have sent the scale down + boolean allChildrenScaleDown = false; + for (Monitor monitor : this.aliasToActiveMonitorsMap.values()) { + if (instanceContext.getScalingDownBeyondMinEvent(monitor.getId()) == null) { + allChildrenScaleDown = false; + break; + } else { + allChildrenScaleDown = true; + } + } + //all the children sent the scale down only, it will try to scale down + if (allChildrenScaleDown) { + if (hasScalingDependents) { + //Parent has to handle this scale down as by dependent scale down + ScalingDownBeyondMinEvent newScalingDownBeyondMinEvent = new ScalingDownBeyondMinEvent(this.id, + nwPartitionContext.getId(), instanceContext.getParentInstanceId()); + this.parent.onChildScalingDownBeyondMinEvent(newScalingDownBeyondMinEvent); + } else { + if (groupScalingEnabled) { + if (nwPartitionContext.getNonTerminatedInstancesCount() > + ((GroupLevelNetworkPartitionContext) + nwPartitionContext).getMinInstanceCount()) { + //send terminating to the specific group instance in the scale down + ApplicationBuilder.handleGroupTerminatingEvent(this.appId, this.id, + instanceContext.getId()); + } + } else { + //Parent has to handle this scale down as by parent group scale down or application scale down + ScalingDownBeyondMinEvent newScalingDownBeyondMinEvent = new ScalingDownBeyondMinEvent(this.id, + nwPartitionContext.getId(), instanceContext.getParentInstanceId()); + this.parent.onChildScalingDownBeyondMinEvent(newScalingDownBeyondMinEvent); + } + } - if(groupScalingEnabled){ + } + //Resetting the events + instanceContext.setIdToScalingDownBeyondMinEvent( + new HashMap<String, ScalingDownBeyondMinEvent>()); + } + + private void createGroupInstanceOnScaling(final NetworkPartitionContext networkPartitionContext, + final String parentInstanceId) { + if (groupScalingEnabled) { + if (networkPartitionContext.getPendingInstancesCount() == 0) { + //one of the child is loaded and max out. + // Hence creating new group instance + if (log.isDebugEnabled()) { + log.debug("Handling group scaling for the [group] " + id + + "upon a max out event from " + + "the children"); + } + boolean createOnDemand = createInstanceOnDemand(parentInstanceId); + if (!createOnDemand) { + //couldn't create new instance. Hence notifying the parent + Runnable sendScaleMaxOut = new Runnable() { + @Override + public void run() { + MonitorStatusEventBuilder.handleScalingOverMaxEvent(parent, + networkPartitionContext.getId(), + parentInstanceId, + appId); + } + }; + sendScaleMaxOut.run(); + } + } else { + if (log.isDebugEnabled()) { + log.debug("Pending Group instance found. " + + "Hence waiting for it to become active"); + } + } - String networkPartitionId = scalingDownBeyondMinEvent.getNetworkPartitionId(); - String instanceId = scalingDownBeyondMinEvent.getInstanceId(); - getNetworkPartitionContext(networkPartitionId).getInstanceContext(instanceId). - addScalingDownBeyondMinEvent(scalingDownBeyondMinEvent); } else { + //notifying the parent if no group scaling enabled here + Runnable sendScaleMaxOut = new Runnable() { + @Override + public void run() { + MonitorStatusEventBuilder.handleScalingOverMaxEvent(parent, + networkPartitionContext.getId(), + parentInstanceId, + appId); + } + }; + sendScaleMaxOut.run(); - ScalingDownBeyondMinEvent newScalingDownBeyondMinEvent = new ScalingDownBeyondMinEvent(this.id, - scalingDownBeyondMinEvent.getNetworkPartitionId(), scalingDownBeyondMinEvent.getInstanceId()); - this.parent.onChildScalingDownBeyondMinEvent(newScalingDownBeyondMinEvent); } } - private void handleScalingDownBeyondMin(InstanceContext instanceContext, NetworkPartitionContext nwPartitionContext) { - - //TODO implement action on scaling down the group instances + private void notifyParentOnMaxOut(NetworkPartitionContext networkPartitionContext, + InstanceContext instanceContext) { + //has scaling dependents. Should notify the parent + if (log.isDebugEnabled()) { + log.debug("This [Group] " + id + " [scale-up] dependencies. " + + "Hence notifying the [parent] " + parent.getId()); + } + //notifying the parent when scale dependents found + int maxInstances = ((GroupLevelNetworkPartitionContext) + networkPartitionContext).getMaxInstanceCount(); + if (groupScalingEnabled && maxInstances > networkPartitionContext. + getNonTerminatedInstancesCount()) { + //increase group by one more instance + float minInstances = ((GroupLevelNetworkPartitionContext) + networkPartitionContext).getMinInstanceCount(); + + float factor = (minInstances + 1) / minInstances; + MonitorStatusEventBuilder. + handleClusterScalingEvent(parent, + networkPartitionContext.getId(), + instanceContext.getParentInstanceId(), + factor, id); + } else { + MonitorStatusEventBuilder.handleScalingOverMaxEvent(parent, + networkPartitionContext.getId(), + instanceContext.getParentInstanceId(), + id); + } } /** @@ -376,50 +428,8 @@ public class GroupMonitor extends ParentComponentMonitor { final NetworkPartitionContext networkPartitionContext = this.networkPartitionCtxts. get(networkPartitionId); - if (groupScalingEnabled) { - if(networkPartitionContext.getPendingInstancesCount() == 0) { - //one of the child is loaded and max out. - // Hence creating new group instance - if(log.isDebugEnabled()) { - log.debug("Handling group scaling for the [group] " + id + - "upon a max out event from " + - "the children"); - } - boolean createOnDemand = createInstanceOnDemand(parentInstanceId); - if (!createOnDemand) { - //couldn't create new instance. Hence notifying the parent - Runnable sendScaleMaxOut = new Runnable() { - @Override - public void run() { - MonitorStatusEventBuilder.handleScalingOverMaxEvent(parent, - networkPartitionContext.getId(), - parentInstanceId, - appId); - } - }; - sendScaleMaxOut.run(); - } - } else { - if(log.isDebugEnabled()) { - log.debug("Pending Group instance found. " + - "Hence waiting for it to become active"); - } - } + createGroupInstanceOnScaling(networkPartitionContext, parentInstanceId); - } else { - //notifying the parent if no group scaling enabled here - Runnable sendScaleMaxOut = new Runnable() { - @Override - public void run() { - MonitorStatusEventBuilder.handleScalingOverMaxEvent(parent, - networkPartitionContext.getId(), - parentInstanceId, - appId); - } - }; - sendScaleMaxOut.run(); - - } } public boolean isGroupScalingEnabled() { http://git-wip-us.apache.org/repos/asf/stratos/blob/22f46e07/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/ParentComponentMonitor.java ---------------------------------------------------------------------- diff --git a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/ParentComponentMonitor.java b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/ParentComponentMonitor.java index 73766e2..949cfe4 100644 --- a/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/ParentComponentMonitor.java +++ b/components/org.apache.stratos.autoscaler/src/main/java/org/apache/stratos/autoscaler/monitor/component/ParentComponentMonitor.java @@ -287,6 +287,14 @@ public abstract class ParentComponentMonitor extends Monitor implements Runnable } + public void onChildScalingDownBeyondMinEvent(ScalingDownBeyondMinEvent scalingDownBeyondMinEvent) { + + String networkPartitionId = scalingDownBeyondMinEvent.getNetworkPartitionId(); + String instanceId = scalingDownBeyondMinEvent.getInstanceId(); + getNetworkPartitionContext(networkPartitionId).getInstanceContext(instanceId). + addScalingDownBeyondMinEvent(scalingDownBeyondMinEvent); + } + @Override public void onChildScalingOverMaxEvent(ScalingUpBeyondMaxEvent scalingUpBeyondMaxEvent) { if (log.isDebugEnabled()) { @@ -772,8 +780,6 @@ public abstract class ParentComponentMonitor extends Monitor implements Runnable return scalingDependencies; } - public abstract void onChildScalingDownBeyondMinEvent(ScalingDownBeyondMinEvent scalingDownBeyondMinEvent); - private class MonitorAdder implements Runnable { private ApplicationChildContext context; private ParentComponentMonitor parent;
