forked from cloudsimplus/cloudsimplus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
LoadBalancerByHorizontalVmScalingExample.java
303 lines (270 loc) · 12.2 KB
/
LoadBalancerByHorizontalVmScalingExample.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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
120
121
122
123
124
125
126
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
/*
* CloudSim Plus: A modern, highly-extensible and easier-to-use Framework for
* Modeling and Simulation of Cloud Computing Infrastructures and Services.
* http://cloudsimplus.org
*
* Copyright (C) 2015-2016 Universidade da Beira Interior (UBI, Portugal) and
* the Instituto Federal de Educação Ciência e Tecnologia do Tocantins (IFTO, Brazil).
*
* This file is part of CloudSim Plus.
*
* CloudSim Plus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CloudSim Plus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CloudSim Plus. If not, see <http://www.gnu.org/licenses/>.
*/
package org.cloudsimplus.examples.autoscaling;
import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicySimple;
import org.cloudbus.cloudsim.brokers.DatacenterBroker;
import org.cloudbus.cloudsim.brokers.DatacenterBrokerSimple;
import org.cloudbus.cloudsim.core.Simulation;
import org.cloudbus.cloudsim.distributions.ContinuousDistribution;
import org.cloudbus.cloudsim.distributions.UniformDistr;
import org.cloudbus.cloudsim.schedulers.cloudlet.CloudletSchedulerTimeShared;
import org.cloudsimplus.autoscaling.HorizontalVmScaling;
import org.cloudsimplus.autoscaling.HorizontalVmScalingSimple;
import org.cloudbus.cloudsim.cloudlets.Cloudlet;
import org.cloudbus.cloudsim.cloudlets.CloudletSimple;
import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.datacenters.Datacenter;
import org.cloudbus.cloudsim.datacenters.DatacenterCharacteristics;
import org.cloudbus.cloudsim.datacenters.DatacenterCharacteristicsSimple;
import org.cloudbus.cloudsim.datacenters.DatacenterSimple;
import org.cloudbus.cloudsim.hosts.Host;
import org.cloudbus.cloudsim.hosts.HostSimple;
import org.cloudbus.cloudsim.provisioners.PeProvisionerSimple;
import org.cloudbus.cloudsim.provisioners.ResourceProvisionerSimple;
import org.cloudbus.cloudsim.resources.Pe;
import org.cloudbus.cloudsim.resources.PeSimple;
import org.cloudbus.cloudsim.schedulers.vm.VmScheduler;
import org.cloudbus.cloudsim.schedulers.vm.VmSchedulerTimeShared;
import org.cloudbus.cloudsim.util.Log;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModel;
import org.cloudbus.cloudsim.utilizationmodels.UtilizationModelFull;
import org.cloudbus.cloudsim.vms.Vm;
import org.cloudbus.cloudsim.vms.VmSimple;
import org.cloudsimplus.listeners.EventInfo;
import org.cloudsimplus.listeners.EventListener;
import org.cloudsimplus.builders.tables.CloudletsTableBuilder;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
import static java.util.Comparator.comparingDouble;
/**
* An example that balances load by dynamically creating VMs according
* to the arrival of Cloudlets.
* Cloudlets are {@link #createNewCloudlets(EventInfo) dynamically created and submitted to the broker
* at specific time intervals}.
* A {@link HorizontalVmScalingSimple}
* is set to each {@link #createListOfScalableVms(int) initially created VM},
* that will check at {@link #SCHEDULING_INTERVAL specific time intervals}
* if the VM {@link #isVmOverloaded(Vm) is overloaded or not} to then
* request the creation of a new VM to attend the arriving Cloudlets.
*
* <p>The example uses the CloudSim Plus {@link EventListener} feature
* to enable monitoring the simulation and dynamically creating objects such as Cloudlets and VMs.
* It relies on
* <a href="http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html">Java 8 Lambda Expressions</a>
* to create an Listener for the {@link Simulation#addOnClockTickListener(EventListener) onClockTick event}
* in order to get notified when the simulation clock advances and then create and submit new cloudlets.
* </p>
*
* @author Manoel Campos da Silva Filho
* @since CloudSim Plus 1.0
*/
public class LoadBalancerByHorizontalVmScalingExample {
/**
* The interval in which the Datacenter will schedule events.
* As lower is this interval, sooner the processing of VMs and Cloudlets
* is updated and you will get more notifications about the simulation execution.
* However, as higher is this value, it can affect the simulation performance.
*
* <p>For this example, a large schedule interval such as 15 will make that just
* at every 15 seconds the processing of VMs is updated. If a VM is overloaded, just
* after this time the creation of a new one will be requested
* by the VM's {@link HorizontalVmScaling Horizontal Scaling} mechanism.</p>
*
* <p>If this interval is defined using a small value, you may get
* more dynamically created VMs than expected. Accordingly, this value
* has to be trade-off.
* For more details, see {@link Datacenter#getSchedulingInterval()}.</p>
*/
private static final int SCHEDULING_INTERVAL = 5;
/**
* The interval to request the creation of new Cloudlets.
*/
private static final int CLOUDLETS_CREATION_INTERVAL = SCHEDULING_INTERVAL * 2;
private static final int HOSTS = 50;
private static final int HOST_PES = 32;
private static final int VMS = 4;
private static final int CLOUDLETS = 6;
private final CloudSim simulation;
private DatacenterBroker broker0;
private List<Host> hostList;
private List<Vm> vmList;
private List<Cloudlet> cloudletList;
/**
* Different lengths that will be randomly assigned to created Cloudlets.
*/
private static final long[] CLOUDLET_LENGTHS = {2000, 4000, 10000, 16000, 2000, 30000, 20000};
private ContinuousDistribution rand;
private int createdCloudlets;
private int createsVms;
public static void main(String[] args) {
new LoadBalancerByHorizontalVmScalingExample();
}
/**
* Default constructor that builds the simulation scenario and starts the simulation.
*/
public LoadBalancerByHorizontalVmScalingExample() {
/*You can remove the seed to get a dynamic one, based on current computer time.
* With a dynamic seed you will get different results at each simulation run.*/
final long seed = 1;
rand = new UniformDistr(0, CLOUDLET_LENGTHS.length, seed);
hostList = new ArrayList<>(HOSTS);
vmList = new ArrayList<>(VMS);
cloudletList = new ArrayList<>(CLOUDLETS);
simulation = new CloudSim();
simulation.addOnClockTickListener(this::createNewCloudlets);
createDatacenter();
broker0 = new DatacenterBrokerSimple(simulation);
vmList.addAll(createListOfScalableVms(VMS));
createCloudletList();
broker0.submitVmList(vmList);
broker0.submitCloudletList(cloudletList);
simulation.start();
printSimulationResults();
}
private void printSimulationResults() {
List<Cloudlet> finishedCloudlets = broker0.getCloudletFinishedList();
Comparator<Cloudlet> sortByVmId = comparingDouble(c -> c.getVm().getId());
Comparator<Cloudlet> sortByStartTime = comparingDouble(c -> c.getExecStartTime());
finishedCloudlets.sort(sortByVmId.thenComparing(sortByStartTime));
new CloudletsTableBuilder(finishedCloudlets).build();
}
private void createCloudletList() {
for (int i = 0; i < CLOUDLETS; i++) {
cloudletList.add(createCloudlet());
}
}
/**
* Creates new Cloudlets at every 10 seconds up to the 50th simulation second.
* A reference to this method is set as the {@link EventListener}
* to the {@link Simulation#addOnClockTickListener(EventListener)}.
* The method is then called every time the simulation clock advances.
*
* @param eventInfo the information about the OnClockTick event that has happened
*/
private void createNewCloudlets(EventInfo eventInfo) {
final long time = (long) eventInfo.getTime();
if (time % CLOUDLETS_CREATION_INTERVAL == 0 && time <= 50) {
final int numberOfCloudlets = 4;
Log.printFormattedLine("\t#Creating %d Cloudlets at time %d.", numberOfCloudlets, time);
List<Cloudlet> newCloudlets = new ArrayList<>(numberOfCloudlets);
for (int i = 0; i < numberOfCloudlets; i++) {
Cloudlet cloudlet = createCloudlet();
cloudletList.add(cloudlet);
newCloudlets.add(cloudlet);
}
broker0.submitCloudletList(newCloudlets);
}
}
/**
* Creates a Datacenter and its Hosts.
*/
private void createDatacenter() {
for (int i = 0; i < HOSTS; i++) {
hostList.add(createHost());
}
DatacenterCharacteristics characteristics = new DatacenterCharacteristicsSimple(hostList);
Datacenter dc0 = new DatacenterSimple(simulation, characteristics, new VmAllocationPolicySimple());
dc0.setSchedulingInterval(SCHEDULING_INTERVAL);
}
private Host createHost() {
List<Pe> peList = new ArrayList<>(HOST_PES);
for (int i = 0; i < HOST_PES; i++) {
peList.add(new PeSimple(1000, new PeProvisionerSimple()));
}
final long ram = 2048; // in Megabytes
final long storage = 1000000; // in Megabytes
final long bw = 10000; //in Megabits/s
VmScheduler vmScheduler = new VmSchedulerTimeShared();
final int id = hostList.size();
return new HostSimple(ram, bw, storage, peList)
.setRamProvisioner(new ResourceProvisionerSimple())
.setBwProvisioner(new ResourceProvisionerSimple())
.setVmScheduler(vmScheduler);
}
/**
* Creates a list of initial VMs in which each VM is able to scale horizontally
* when it is overloaded.
*
* @param numberOfVms number of VMs to create
* @return the list of scalable VMs
* @see #createHorizontalVmScaling(Vm)
*/
private List<Vm> createListOfScalableVms(final int numberOfVms) {
List<Vm> newList = new ArrayList<>(numberOfVms);
for (int i = 0; i < numberOfVms; i++) {
Vm vm = createVm();
createHorizontalVmScaling(vm);
newList.add(vm);
}
return newList;
}
/**
* Creates a {@link HorizontalVmScaling} object for a given VM.
*
* @param vm the VM in which the Horizontal Scaling will be created
* @see #createListOfScalableVms(int)
*/
private void createHorizontalVmScaling(Vm vm) {
HorizontalVmScaling horizontalScaling = new HorizontalVmScalingSimple();
horizontalScaling
.setVmSupplier(this::createVm)
.setOverloadPredicate(this::isVmOverloaded);
vm.setHorizontalScaling(horizontalScaling);
}
/**
* Creates a Vm object.
*
* @return the created Vm
*/
private Vm createVm() {
final int id = createsVms++;
Vm vm = new VmSimple(id, 1000, 2)
.setRam(512).setBw(1000).setSize(10000)
.setCloudletScheduler(new CloudletSchedulerTimeShared());
return vm;
}
/**
* A {@link Predicate} that checks if a given VM is overloaded or not based on upper CPU utilization threshold.
* A reference to this method is assigned to each Horizontal VM Scaling created.
*
* @param vm the VM to check if it is overloaded
* @return true if the VM is overloaded, false otherwise
* @see #createHorizontalVmScaling(Vm)
*/
private boolean isVmOverloaded(Vm vm) {
return vm.getCpuPercentUsage() > 0.7;
}
private Cloudlet createCloudlet() {
final int id = createdCloudlets++;
//randomly selects a length for the cloudlet
final long length = CLOUDLET_LENGTHS[(int) rand.sample()];
UtilizationModel utilization = new UtilizationModelFull();
return new CloudletSimple(id, length, 2)
.setFileSize(1024)
.setOutputSize(1024)
.setUtilizationModel(utilization);
}
}