Request Scheduler
The "RequestScheduler" class is responsible for scheduling "vRequest" instances onto "vContainer" instances in a simulated cloud environment. Since the computational resource usage of a "vRequest" cannot be known in advance due to the dynamic generation of "vProcess" and "vPacket" during execution, the "RequestScheduler" behaves like a load balancer, distributing "vRequest" instances among "vContainer" instances.
By default, the "RequestScheduler" uses a logic that directs each "vRequest" to the "vContainer" instance that is currently executing the least number of "vRequest" instances. This default logic ensures a balanced distribution of workloads across available "vContainer" instances. However, the "RequestScheduler" class also provides an abstract member function that allows developers to customize the scheduling logic according to specific requirements.
Similar to the "ContainerScheduler", the scheduling process in the "RequestScheduler" is implemented as an event that is triggered whenever a new "vRequest" is created, a current "vRequest" is terminated or a new 'vContainer" is scheduled. This ensures that all unscheduled "vRequest" instances are processed and assigned to appropriate "vContainer" instances as soon as possible. During the simulation, only one "RequestScheduler" scheduling process can exist at any time to maintain the consistency of workload distribution.
RequestScheduler
Source code in PyCloudSim\scheduler\request_scheduler.py
| class RequestScheduler:
def __init__(self) -> None:
"""Request Scheduler
"""
self._active_process: Actor = None # type: ignore
simulation._request_scheduler = self
def schedule(self):
"""Schedule requests.
"""
def _schedule():
LOGGER.debug(
f"{simulation.now:0.2f}:\tRequest Scheduler is scheduling...{len([req for req in simulation.REQUESTS if req.scheduled == False])} requests."
)
self._active_process = None # type: ignore
simulation.REQUESTS.sort(key=lambda x: x.priority)
for request in simulation.REQUESTS:
source_endpoint = None
target_endpoint = None
if not request.scheduled and request.created:
# find the containers
if isinstance(request.source, vMicroservice):
source_endpoint = request.source.service.loadbalancer()
else:
source_endpoint = None
if isinstance(request.target, vMicroservice):
target_endpoint = request.target.service.loadbalancer()
else:
target_endpoint = None
# check if request schedulable
if (
source_endpoint is None
and isinstance(request.source, vMicroservice)
) or (
target_endpoint is None
and isinstance(request.target, vMicroservice)
):
LOGGER.debug(f"{simulation.now:0.2f}:\tvRequest {request.label} not schedulable, {request.source} or {request.target} not available.")
continue
request._scheduled_at = simulation.now
request.status.append(SCHEDULED)
if request.flow is not None and not request.flow.scheduled:
request.flow._scheduled_at = simulation.now
request.flow.status.append(SCHEDULED)
if source_endpoint is not None:
request._source_endpoint = source_endpoint
source_endpoint.accept_request(request)
if target_endpoint is not None:
request._target_endpoint = target_endpoint
target_endpoint.accept_request(request)
request.execute()
if self._active_process is None:
self._active_process = Actor(
at=simulation.now,
action=_schedule,
label=f"vRequest Scedule Start",
priority=REQUEST_SCHEDULER,
)
@property
def active_process(self) -> Actor:
"""return the active process of the request scheduler."""
return self._active_process
|
active_process: Actor
property
return the active process of the request scheduler.
__init__()
Request Scheduler
Source code in PyCloudSim\scheduler\request_scheduler.py
| def __init__(self) -> None:
"""Request Scheduler
"""
self._active_process: Actor = None # type: ignore
simulation._request_scheduler = self
|
schedule()
Schedule requests.
Source code in PyCloudSim\scheduler\request_scheduler.py
| def schedule(self):
"""Schedule requests.
"""
def _schedule():
LOGGER.debug(
f"{simulation.now:0.2f}:\tRequest Scheduler is scheduling...{len([req for req in simulation.REQUESTS if req.scheduled == False])} requests."
)
self._active_process = None # type: ignore
simulation.REQUESTS.sort(key=lambda x: x.priority)
for request in simulation.REQUESTS:
source_endpoint = None
target_endpoint = None
if not request.scheduled and request.created:
# find the containers
if isinstance(request.source, vMicroservice):
source_endpoint = request.source.service.loadbalancer()
else:
source_endpoint = None
if isinstance(request.target, vMicroservice):
target_endpoint = request.target.service.loadbalancer()
else:
target_endpoint = None
# check if request schedulable
if (
source_endpoint is None
and isinstance(request.source, vMicroservice)
) or (
target_endpoint is None
and isinstance(request.target, vMicroservice)
):
LOGGER.debug(f"{simulation.now:0.2f}:\tvRequest {request.label} not schedulable, {request.source} or {request.target} not available.")
continue
request._scheduled_at = simulation.now
request.status.append(SCHEDULED)
if request.flow is not None and not request.flow.scheduled:
request.flow._scheduled_at = simulation.now
request.flow.status.append(SCHEDULED)
if source_endpoint is not None:
request._source_endpoint = source_endpoint
source_endpoint.accept_request(request)
if target_endpoint is not None:
request._target_endpoint = target_endpoint
target_endpoint.accept_request(request)
request.execute()
if self._active_process is None:
self._active_process = Actor(
at=simulation.now,
action=_schedule,
label=f"vRequest Scedule Start",
priority=REQUEST_SCHEDULER,
)
|