Skip to content

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,
        )