Esempio n. 1
0
 def __init__(self, clock, cluster_nodes):
     self.clock = clock
     self.cluster_nodes = []
     for cluster_node in cluster_nodes:
         if not cluster_node.startswith('http://'):
             cluster_node = 'http://%s' % (cluster_node,)
         self.cluster_nodes.append((cluster_node, requests.Session()))
     random.shuffle(self.cluster_nodes)
     self.breaker = CircuitBreakerSet(clock.time, logging.getLogger(
             'service-discovery-client'))
     self.breaker.handle_error(RequestException)
     self.breaker.handle_error(ConnectionError)
     self.breaker.handle_error(TooManyRedirects)
Esempio n. 2
0
 def __init__(self, clock, cluster_nodes=None):
     self.clock = clock
     self.cluster_nodes = []
     if cluster_nodes is None:
         cluster_nodes = os.getenv(
             'GILLIAM_SERVICE_REGISTRY', '').split(',')
     for cluster_node in cluster_nodes:
         if not cluster_node.startswith('http://'):
             cluster_node = 'http://%s' % (cluster_node,)
         self.cluster_nodes.append((cluster_node, requests.Session()))
     random.shuffle(self.cluster_nodes)
     self.breaker = CircuitBreakerSet(clock.time, logging.getLogger(
             'service-discovery-client'))
     self.breaker.handle_error(RequestException)
     self.breaker.handle_error(ConnectionError)
     self.breaker.handle_error(TooManyRedirects)
     # backward compatible
     self.resolve = Resolver(self).resolve_url
Esempio n. 3
0
class ServiceRegistryClient(object):

    def __init__(self, clock, cluster_nodes=None):
        self.clock = clock
        self.cluster_nodes = []
        if cluster_nodes is None:
            cluster_nodes = os.getenv(
                'GILLIAM_SERVICE_REGISTRY', '').split(',')
        for cluster_node in cluster_nodes:
            if not cluster_node.startswith('http://'):
                cluster_node = 'http://%s' % (cluster_node,)
            self.cluster_nodes.append((cluster_node, requests.Session()))
        random.shuffle(self.cluster_nodes)
        self.breaker = CircuitBreakerSet(clock.time, logging.getLogger(
                'service-discovery-client'))
        self.breaker.handle_error(RequestException)
        self.breaker.handle_error(ConnectionError)
        self.breaker.handle_error(TooManyRedirects)
        # backward compatible
        self.resolve = Resolver(self).resolve_url

    def _request(self, method, uri, **kwargs):
        """Issue a request to SOME of the nodes in the cluster."""
        for node, session in self.cluster_nodes:
            try:
                with self.breaker.context(node):
                    response = session.request(method, urljoin(node, uri),
                                               **kwargs)
                    if response.status_code >= 500:
                        raise RequestException()
                    return response
            except CircuitOpenError:
                continue
        else:
            raise Exception("NO MACHIEN TO TALK TOOO")

    def register(self, form_name, service, instance_name, data):
        """Register an instance with a formation."""
        return _Registration(self, form_name, service, instance_name, data).start()

    def build_announcement(self, formation, service, instance,
                           ports={}, **kwargs):
        announcement = {
            'formation': formation, 'service': service,
            'instance': instance, 'ports': ports.copy(),
            }
        announcement.update(kwargs)
        return announcement

    def query_formation(self, form_name, factory=dict):
        """Query all instances of a formation.
        
        Will return a generator that yields (instance name, data) for
        each instance.

        @param factory: Data factory.  Will be passed a JSON object of
            the instance data, expects to return a representation of
            that data.
        """
        response = self._request('GET', '/%s' % (form_name,))
        response.raise_for_status()
        for key, data in response.json().items():
            yield (key, factory(data))

    def formation_cache(self, form_name, factory=dict, interval=15):
        """Return a cache for a specific formation that will be kept
        up to date until stopped.
        """
        return _FormationCache(self, form_name, factory, interval).start()
Esempio n. 4
0
class ServiceRegistryClient(object):

    def __init__(self, clock, cluster_nodes):
        self.clock = clock
        self.cluster_nodes = []
        for cluster_node in cluster_nodes:
            if not cluster_node.startswith('http://'):
                cluster_node = 'http://%s' % (cluster_node,)
            self.cluster_nodes.append((cluster_node, requests.Session()))
        random.shuffle(self.cluster_nodes)
        self.breaker = CircuitBreakerSet(clock.time, logging.getLogger(
                'service-discovery-client'))
        self.breaker.handle_error(RequestException)
        self.breaker.handle_error(ConnectionError)
        self.breaker.handle_error(TooManyRedirects)
        # backward compatible
        self.resolve = Resolver(self).resolve_url

    def _request(self, method, uri, **kwargs):
        """Issue a request to SOME of the nodes in the cluster."""
        for node, session in self.cluster_nodes:
            try:
                with self.breaker.context(node):
                    response = session.request(method, urljoin(node, uri),
                                               **kwargs)
                    if response.status_code >= 500:
                        raise RequestException()
                    return response
            except CircuitOpenError:
                continue
        else:
            raise Exception("NO MACHIEN TO TALK TOOO")

    def register(self, form_name, service, instance_name, data):
        """Register an instance with a formation."""
        return _Registration(self, form_name, service, instance_name, data).start()

    def build_announcement(self, formation, service, instance,
                           ports={}, **kwargs):
        announcement = {
            'formation': formation, 'service': service,
            'instance': instance, 'ports': ports.copy(),
            }
        announcement.update(kwargs)
        return announcement

    def query_formation(self, form_name, factory=dict):
        """Query all instances of a formation.
        
        Will return a generator that yields (instance name, data) for
        each instance.

        @param factory: Data factory.  Will be passed a JSON object of
            the instance data, expects to return a representation of
            that data.
        """
        response = self._request('GET', '/%s' % (form_name,))
        response.raise_for_status()
        for key, data in response.json().items():
            yield (key, factory(data))

    def formation_cache(self, form_name, factory=dict, interval=15):
        """Return a cache for a specific formation that will be kept
        up to date until stopped.
        """
        return _FormationCache(self, form_name, factory, interval).start()
Esempio n. 5
0
class ServiceRegistryClient(object):

    def __init__(self, clock, cluster_nodes):
        self.clock = clock
        self.cluster_nodes = []
        for cluster_node in cluster_nodes:
            if not cluster_node.startswith('http://'):
                cluster_node = 'http://%s' % (cluster_node,)
            self.cluster_nodes.append((cluster_node, requests.Session()))
        random.shuffle(self.cluster_nodes)
        self.breaker = CircuitBreakerSet(clock.time, logging.getLogger(
                'service-discovery-client'))
        self.breaker.handle_error(RequestException)
        self.breaker.handle_error(ConnectionError)
        self.breaker.handle_error(TooManyRedirects)

    def _request(self, method, uri, **kwargs):
        """Issue a request to SOME of the nodes in the cluster."""
        for node, session in self.cluster_nodes:
            try:
                with self.breaker.context(node):
                    response = session.request(method, urljoin(node, uri),
                                               **kwargs)
                    if response.status_code >= 500:
                        raise RequestException()
                    return response
            except CircuitOpenError:
                continue
        else:
            raise Exception("NO MACHIEN TO TALK TOOO")

    def register(self, form_name, instance_name, data):
        """Register an instance with a formation."""
        return _Registration(self, form_name, instance_name, data).start()

    def query_formation(self, form_name, factory=dict):
        """Query all instances of a formation.
        
        Will return a generator that yields (instance name, data) for
        each instance.

        @param factory: Data factory.  Will be passed a JSON object of
            the instance data, expects to return a representation of
            that data.
        """
        response = self._request('GET', '/%s' % (form_name,))
        response.raise_for_status()
        for key, data in response.json().items():
            yield (key, factory(data))

    def formation_cache(self, form_name, factory=dict, interval=15):
        """Return a cache for a specific formation that will be kept
        up to date until stopped.
        """
        return _FormationCache(self, form_name, factory, interval).start()

    def _resolve_port(self, d, port):
        if str(port) not in d['ports']:
            raise ValueError("instance do not expose port")
        return d['ports'][str(port)]

    # FIXME: refactor

    def _resolve_any(self, port, formation, service):
        alts = [d for (k, d) in self.query_formation(formation)
                if k.startswith(service + '.')]
        if not alts:
            raise Exception("no instances")
        alt = random.choice(alts)
        return alt['host'], self._resolve_port(alt, port)

    def _resolve_specific(self, port, formation, service, name):
        alts = [d for (k, d) in self.query_formation(formation)
                if k.startswith(service + '.' + name)]
        if not alts:
            raise Exception("no instances")
        alt = random.choice(alts)
        return alt['host'], self._resolve_port(alt, port)

    def resolve(self, url):
        """Resolve a URL into a direct url."""
        u = urlparse.urlsplit(url)
        assert u.hostname.endswith('.service'), "must end with .service"
        parts = u.hostname.split('.')
        if len(parts) == 4:
            hostname, port = self._resolve_specific(u.port, parts[2],
                                                    parts[1], parts[0])
        elif len(parts) == 3:
            hostname, port = self._resolve_any(u.port, parts[1], parts[0])
        netloc = '%s:%d' % (hostname, port)
        return urlparse.urlunsplit((u.scheme, netloc, u.path,
                                    u.query, u.fragment))