Round-Robin Load Balancing

Step 4: Round-Robin Load Balancing

Discovery usually ends with "give me one healthy instance to call." Spreading calls evenly is round-robin: keep a per-service counter and hand out healthy instances in rotation, wrapping around. Only healthy instances are eligible, an expired or deregistered one is never returned, and when none are available the caller gets None so it can back off.

Build the picker:

  • pick(service, now): from the current healthy list, return the next instance in round-robin order (advancing a per-service counter in self._rr); return None if there are no healthy instances.
Hints
Starter code
class ServiceRegistry:
    def __init__(self, ttl=10):
        self.ttl = ttl
        self.instances = {}
        self._rr = {}

    def register(self, service, instance_id, now):
        self.instances.setdefault(service, {})[instance_id] = now

    def healthy(self, service, now):
        svc = self.instances.get(service, {})
        return sorted(i for i, last in svc.items() if now - last <= self.ttl)

    def heartbeat(self, service, instance_id, now):
        svc = self.instances.get(service, {})
        if instance_id in svc:
            svc[instance_id] = now
            return True
        return False

    def deregister(self, service, instance_id):
        self.instances.get(service, {}).pop(instance_id, None)

    def pick(self, service, now):
        """Return the next healthy instance in round-robin order, or None."""
        options = self.healthy(service, now)
        if not options:
            return None
        # TODO: options is the sorted healthy list. Take this service's counter
        #   from self._rr (missing means zero), reduce it modulo the number of
        #   options to choose one, then bump that stored counter by one so the
        #   next call lands on the following instance. Hand the chosen id back.
        pass
Write it on a laptop

The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.