Class: Cloudmaster::PoolManager
- Inherits:
-
Object
- Object
- Cloudmaster::PoolManager
- Defined in:
- app/pool_manager.rb
Overview
PoolManager
Manages one InstancePool, which is collections of EC2 instances
running the same image.
The InstancePoolMaanger is responsible for starting and terminating
instances.
It's policies are meant to balance acceptable performance while
minimizing cost.
To help achieve this goal, the PoolManager receives
status reports from instances, through a status queue.
Two classes of policies are defined: job and resource.
These roughly correspond to stateless and stateful services.
==Job Policy==
In the job policy, instances are assigned work through a work queue.
* Each request is stateless, and can be serviceed by any instance.
* Each instance processes one request at a time.
* Each instance is either starting_up or active.
* Once it is active, it is either busy (load 1.0) or idle (load 0.0).
At startup, the instance reports when it is ready to begin processing, and
enters the active state.
Each instance reports the load through the status queue when it
starts/stops processing a job.
The job policy aims to keep the work queue to a reasonable size while not
maintaining an excessive number of idle instances.
==Resource Policy==
Instance managed by theresource policy have stateful associations with
clients, and provide them services on demand.
* Each instance processes requests made by clients as requested.
* An external entity (the alllocator) assigns clients to instances
based on an instance report, which lists the active instances
and their associated load.
* The instance report (called the active set) is stored in
S3, at a configurable bucket and key.
* The allocator assigns clients to instances, and also creates a
work-queue entry each time it assigns a new client.
* The allocator is expected to assign clients only to those instances
listed in the active set.
* The work queue is emptied by cloudmaster.
* Each instance may be starting_up, active, or shutting_down.
* At startup, the instance reports when it is ready to begin processing,
and enters the active state.
* The policy decides when to shut down an instance.
It puts it in the shut_down state, but does not stop
it immediately (to avoid disturbing existing clients).
Instances in shutting_down state with zero load, or who have
remained in this state for an excessive time are stopped.
* Active instances are available to accept new clients;
shutting_down instances are not.
During any given time period, each instance can be partially busy (load
between 0.0 and 1.0)
Each instance periodically reports is load estimate for that period through
the status queue.
The resource policy seeks to maintain a load between an
upper threshold and a lower threshold.
It starts instances or stops them to achieve this.
Instance Attribute Summary collapse
-
#instances ⇒ Object
readonly
for testing only.
-
#logger ⇒ Object
readonly
for testing only.
Instance Method Summary collapse
-
#initialize(config) ⇒ PoolManager
constructor
Set up PoolManager.
-
#run(end_time = nil) ⇒ Object
Main loop of cloudmaster.
-
#shutdown ⇒ Object
Shut down the manager.
Constructor Details
#initialize(config) ⇒ PoolManager
Set up PoolManager. Creates objects used to access SQS and EC2. Creates instance pool, policy classes, repoter, and queues. Actual processing does not start until “run” is called.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'app/pool_manager.rb', line 82 def initialize(config) # set up AWS access objects keys = [ config[:aws_access_key], config[:aws_secret_key]] aws = AwsContext.instance @ec2 = aws.ec2(*keys) @sqs = aws.sqs(*keys) @s3 = aws.s3(*keys) @config = config # set up reporter @logger = LoggerFactory.create(@config[:logger], @config[:logfile]) @reporter = Reporter.setup(@config[:name], @logger) # Create instance pool. # Used to keep track of instances in the pool. @instances = InstancePool.new(@reporter, @config) # Create a policy class @policy = PolicyFactory.create(@config[:policy], @reporter, @config, @instances) # Create ActiveSet @active_set = ActiveSetFactory.create(@config[:active_set_type], @config) # Create StatusParser @status_parser = StatusParserFactory.create(@config[:status_parser]) unless @config[:instance_log].empty? @reporter.log_instances(@config[:instance_log]) end # Look up the work queues and the image from their names. # Have policy do most of the work. @work_queue = @config.setup_queue(:work_queue, :work_queue_name) @status_queue = @config.setup_queue(:status_queue, :status_queue_name) @ami_id = @config.setup_image(:ami_id, :ami_name) @keep_running = true end |
Instance Attribute Details
#instances ⇒ Object (readonly)
for testing only
76 77 78 |
# File 'app/pool_manager.rb', line 76 def instances @instances end |
#logger ⇒ Object (readonly)
for testing only
76 77 78 |
# File 'app/pool_manager.rb', line 76 def logger @logger end |
Instance Method Details
#run(end_time = nil) ⇒ Object
Main loop of cloudmaster
-
Reads and processes status messages.
-
Starts and stops instances according to policies
-
Detects hung instances, and stops them.
-
Displays periodic reports.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'app/pool_manager.rb', line 127 def run(end_time = nil) summary_period = Periodic.new(@config[:summary_interval].to_i) instance_report_period = Periodic.new(@config[:instance_report_interval].to_i) policy_period = Periodic.new(@config[:policy_interval].to_i) active_set_period = Periodic.new(@config[:active_set_interval].to_i * 60) audit_instances_period = Periodic.new(@config[:audit_instance_interval].to_i * 60) # loop reading messages from the status queue while keep_running(end_time) do # upate instance list and get queue depth audit_instances_period.check do @instances.audit_existing_instances end @work_queue.read_queue_depth break unless @keep_running # start first instance, if necessary, and ensure the # number of running instances stays between maximum and minimum @policy.ensure_limits break unless @keep_running # handle status and log messages (@config[:receive_count].to_i) # update public dns (for new instances) and show summary reports @instances.update_public_dns_all summary_period.check do @reporter.info("Instances: #{@instances.size} Queue Depth: #{@work_queue.queue_depth}") end instance_report_period.check do @reporter.info("---Instance Summary---") @instances.each do |instance| @reporter.info(" #{instance.id} #{instance.report}\n") end @reporter.info("----------------------") end break unless @keep_running # Based on queue depth and load_estimate, make a decision on # whether to start or stop servers. policy_period.check { @policy.apply } active_set_period.check { update_active_set } # Stop instances that have not given recent status. @policy.stop_hung_instances break unless @keep_running Clock.sleep @config[:poll_interval].to_i end end |
#shutdown ⇒ Object
Shut down the manager. This may take a little time.
182 183 184 |
# File 'app/pool_manager.rb', line 182 def shutdown @keep_running = false end |