コード例 #1
0
 def test_shard_id_registers(self):
   ss1 = ServerSet(self.make_zk(self._server.ensemble), self.SERVICE_PATH)
   ss2 = ServerSet(self.make_zk(self._server.ensemble), self.SERVICE_PATH)
   ss1.join(self.INSTANCE1, shard=0)
   ss2.join(self.INSTANCE2, shard=1)
   assert list(ss1) == [ServiceInstance(self.INSTANCE1, shard=0), ServiceInstance(self.INSTANCE2, shard=1)]
   assert list(ss2) == [ServiceInstance(self.INSTANCE1, shard=0), ServiceInstance(self.INSTANCE2, shard=1)]
コード例 #2
0
 def test_async_client_iteration(self):
   ss1 = ServerSet(self.make_zk(self._server.ensemble), self.SERVICE_PATH)
   ss2 = ServerSet(self.make_zk(self._server.ensemble), self.SERVICE_PATH)
   ss1.join(self.INSTANCE1)
   ss2.join(self.INSTANCE2)
   assert list(ss1) == [ServiceInstance(self.INSTANCE1), ServiceInstance(self.INSTANCE2)]
   assert list(ss2) == [ServiceInstance(self.INSTANCE1), ServiceInstance(self.INSTANCE2)]
コード例 #3
0
 def test_client_iteration(self):
   ss = ServerSet(self.make_zk(self._server.ensemble), self.SERVICE_PATH)
   assert list(ss) == []
   ss.join(self.INSTANCE1)
   assert list(ss) == [ServiceInstance(self.INSTANCE1)]
   ss.join(self.INSTANCE2)
   assert list(ss) == [ServiceInstance(self.INSTANCE1), ServiceInstance(self.INSTANCE2)]
コード例 #4
0
    def test_client_watcher(self):
        canceled_endpoints = []
        canceled = threading.Event()
        joined_endpoints = []
        joined = threading.Event()

        def on_join(endpoint):
            joined_endpoints[:] = [endpoint]
            joined.set()

        def on_leave(endpoint):
            canceled_endpoints[:] = [endpoint]
            canceled.set()

        service1 = ServerSet(self.make_zk(self._server.ensemble),
                             self.SERVICE_PATH,
                             on_join=on_join,
                             on_leave=on_leave)
        service2 = ServerSet(self.make_zk(self._server.ensemble),
                             self.SERVICE_PATH)

        member1 = service2.join(self.INSTANCE1)
        joined.wait(2.0)
        assert joined.is_set()
        assert not canceled.is_set()
        assert joined_endpoints == [ServiceInstance(self.INSTANCE1)]
        joined.clear()

        service2.join(self.INSTANCE2)
        joined.wait(2.0)
        assert joined.is_set()
        assert not canceled.is_set()
        assert joined_endpoints == [ServiceInstance(self.INSTANCE2)]
        joined.clear()

        service2.cancel(member1)
        canceled.wait(2.0)
        assert canceled.is_set()
        assert not joined.is_set()
        assert canceled_endpoints == [ServiceInstance(self.INSTANCE1)]
        canceled.clear()
コード例 #5
0
ファイル: test_base.py プロジェクト: CodeWarltz/commons
  def test_client_watcher(self):
    canceled_endpoints = []
    canceled = threading.Event()
    joined_endpoints = []
    joined = threading.Event()

    def on_join(endpoint):
      joined_endpoints[:] = [endpoint]
      joined.set()

    def on_leave(endpoint):
      canceled_endpoints[:] = [endpoint]
      canceled.set()

    service1 = ServerSet(self.make_zk(self._server.ensemble),
        self.SERVICE_PATH, on_join=on_join, on_leave=on_leave)
    service2 = ServerSet(self.make_zk(self._server.ensemble),
        self.SERVICE_PATH)

    member1 = service2.join(self.INSTANCE1)
    joined.wait(2.0)
    assert joined.is_set()
    assert not canceled.is_set()
    assert joined_endpoints == [ServiceInstance(self.INSTANCE1)]
    joined.clear()

    service2.join(self.INSTANCE2)
    joined.wait(2.0)
    assert joined.is_set()
    assert not canceled.is_set()
    assert joined_endpoints == [ServiceInstance(self.INSTANCE2)]
    joined.clear()

    service2.cancel(member1)
    canceled.wait(2.0)
    assert canceled.is_set()
    assert not joined.is_set()
    assert canceled_endpoints == [ServiceInstance(self.INSTANCE1)]
    canceled.clear()
コード例 #6
0
ファイル: serverset.py プロジェクト: EricCen/commons
class ServerSetModule(app.Module):
    """
    Binds this application to a Zookeeper ServerSet.
  """

    OPTIONS = {
        "serverset-enable": options.Option(
            "--serverset-enable",
            default=False,
            action="store_true",
            dest="serverset_module_enable",
            help="Enable the ServerSet module.  Requires --serverset-path and --serverset-primary.",
        ),
        "serverset-ensemble": options.Option(
            "--serverset-ensemble",
            default="zookeeper.local.twitter.com:2181",
            dest="serverset_module_ensemble",
            metavar="HOST[:PORT]",
            help="The serverset ensemble to talk to.  HOST or HOST:PORT pair.  If the HOST is a RR DNS "
            "record, we fan out to the entire ensemble.  If no port is specified, 2181 assumed.",
        ),
        "serverset-path": options.Option(
            "--serverset-path",
            default=None,
            dest="serverset_module_path",
            metavar="PATH",
            type="str",
            help="The serverset path to join, preferably /twitter/service/(role)/(service)/(env) "
            "where env is prod, staging, devel.",
        ),
        "serverset-primary": options.Option(
            "--serverset-primary",
            type="int",
            metavar="PORT",
            dest="serverset_module_primary_port",
            default=None,
            help="Port on which to bind the primary endpoint.",
        ),
        "serverset-shard-id": options.Option(
            "--serverset-shard-id",
            type="int",
            metavar="INT",
            dest="serverset_module_shard_id",
            default=None,
            help="Shard id to assign this serverset entry.",
        ),
        "serverset-extra": options.Option(
            "--serverset-extra",
            default={},
            type="string",
            nargs=1,
            action="callback",
            metavar="NAME:PORT",
            callback=add_port_to("serverset_module_extra"),
            dest="serverset_module_extra",
            help="Additional endpoints to bind.  Format NAME:PORT.  May be specified multiple times.",
        ),
        "serverset-persistence": options.Option(
            "--serverset-persistence",
            "--no-serverset-persistence",
            action="callback",
            callback=set_bool,
            dest="serverset_module_persistence",
            default=True,
            help="If serverset persistence is enabled, if the serverset connection is dropped for any "
            "reason, we will retry to connect forever.  If serverset persistence is turned off, "
            "the application will commit seppuku -- sys.exit(1) -- upon session disconnection.",
        ),
    }

    def __init__(self):
        app.Module.__init__(self, __name__, description="ServerSet module")
        self._zookeeper = None
        self._serverset = None
        self._membership = None
        self._join_args = None
        self._torndown = False
        self._rejoin_event = threading.Event()
        self._joiner = None

    @property
    def serverset(self):
        return self._serverset

    @property
    def zh(self):
        if self._zookeeper:
            return self._zookeeper._zh

    def _assert_valid_inputs(self, options):
        if not options.serverset_module_enable:
            return

        assert (
            options.serverset_module_path is not None
        ), "If serverset module enabled, serverset path must be specified."
        assert (
            options.serverset_module_primary_port is not None
        ), "If serverset module enabled, serverset primary port must be specified."
        assert isinstance(options.serverset_module_extra, dict), "Serverset additional endpoints must be a dictionary!"
        for name, value in options.serverset_module_extra.items():
            assert isinstance(name, str), "Additional endpoints must be named by strings!"
            assert isinstance(value, int), "Additional endpoint ports must be integers!"

        try:
            primary_port = int(options.serverset_module_primary_port)
        except ValueError as e:
            raise ValueError("Could not parse serverset primary port: %s" % e)

    def _construct_serverset(self, options):
        import socket
        import threading
        import zookeeper
        from twitter.common.zookeeper.client import ZooKeeper
        from twitter.common.zookeeper.serverset import Endpoint, ServerSet

        log.debug("ServerSet module constructing serverset.")

        hostname = socket.gethostname()
        primary_port = int(options.serverset_module_primary_port)
        primary = Endpoint(hostname, primary_port)
        additional = dict(
            (port_name, Endpoint(hostname, port_number))
            for port_name, port_number in options.serverset_module_extra.items()
        )

        # TODO(wickman) Add timeout parameterization here.
        self._zookeeper = ZooKeeper(options.serverset_module_ensemble)
        self._serverset = ServerSet(self._zookeeper, options.serverset_module_path)
        self._join_args = (primary, additional)
        self._join_kwargs = {"shard": options.serverset_module_shard_id} if options.serverset_module_shard_id else {}

    def _join(self):
        log.debug("ServerSet module joining serverset.")
        primary, additional = self._join_args
        self._membership = self._serverset.join(
            primary, additional, expire_callback=self.on_expiration, **self._join_kwargs
        )

    def on_expiration(self):
        if self._torndown:
            return

        log.debug("Serverset session expired.")
        if not app.get_options().serverset_module_persistence:
            log.debug("Committing seppuku...")
            sys.exit(1)
        else:
            log.debug("Rejoining...")

        self._rejoin_event.set()

    def setup_function(self):
        options = app.get_options()
        if options.serverset_module_enable:
            self._assert_valid_inputs(options)
            self._construct_serverset(options)
            self._thread = ServerSetJoinThread(self._rejoin_event, self._join)
            self._thread.start()
            self._rejoin_event.set()

    def teardown_function(self):
        self._torndown = True
        if self._membership:
            self._serverset.cancel(self._membership)
            self._zookeeper.stop()
コード例 #7
0
ファイル: serverset.py プロジェクト: ycaihua/twitter-commons
class ServerSetModule(app.Module):
    """
    Binds this application to a Zookeeper ServerSet.
  """
    OPTIONS = {
        'serverset-enable':
        options.Option(
            '--serverset-enable',
            default=False,
            action='store_true',
            dest='serverset_module_enable',
            help=
            'Enable the ServerSet module.  Requires --serverset-path and --serverset-primary.'
        ),
        'serverset-ensemble':
        options.Option(
            '--serverset-ensemble',
            default='zookeeper.local.twitter.com:2181',
            dest='serverset_module_ensemble',
            metavar='HOST[:PORT]',
            help=
            'The serverset ensemble to talk to.  HOST or HOST:PORT pair.  If the HOST is a RR DNS '
            'record, we fan out to the entire ensemble.  If no port is specified, 2181 assumed.'
        ),
        'serverset-path':
        options.Option(
            '--serverset-path',
            default=None,
            dest='serverset_module_path',
            metavar='PATH',
            type='str',
            help=
            'The serverset path to join, preferably /twitter/service/(role)/(service)/(env) '
            'where env is prod, staging, devel.'),
        'serverset-primary':
        options.Option('--serverset-primary',
                       type='int',
                       metavar='PORT',
                       dest='serverset_module_primary_port',
                       default=None,
                       help='Port on which to bind the primary endpoint.'),
        'serverset-shard-id':
        options.Option('--serverset-shard-id',
                       type='int',
                       metavar='INT',
                       dest='serverset_module_shard_id',
                       default=None,
                       help='Shard id to assign this serverset entry.'),
        'serverset-extra':
        options.Option(
            '--serverset-extra',
            default={},
            type='string',
            nargs=1,
            action='callback',
            metavar='NAME:PORT',
            callback=add_port_to('serverset_module_extra'),
            dest='serverset_module_extra',
            help=
            'Additional endpoints to bind.  Format NAME:PORT.  May be specified multiple times.'
        ),
        'serverset-persistence':
        options.Option(
            '--serverset-persistence',
            '--no-serverset-persistence',
            action='callback',
            callback=set_bool,
            dest='serverset_module_persistence',
            default=True,
            help=
            'If serverset persistence is enabled, if the serverset connection is dropped for any '
            'reason, we will retry to connect forever.  If serverset persistence is turned off, '
            'the application will commit seppuku -- sys.exit(1) -- upon session disconnection.'
        ),
    }

    def __init__(self):
        app.Module.__init__(self, __name__, description="ServerSet module")
        self._zookeeper = None
        self._serverset = None
        self._membership = None
        self._join_args = None
        self._torndown = False
        self._rejoin_event = threading.Event()
        self._joiner = None

    @property
    def serverset(self):
        return self._serverset

    @property
    def zh(self):
        if self._zookeeper:
            return self._zookeeper._zh

    def _assert_valid_inputs(self, options):
        if not options.serverset_module_enable:
            return

        assert options.serverset_module_path is not None, (
            'If serverset module enabled, serverset path must be specified.')
        assert options.serverset_module_primary_port is not None, (
            'If serverset module enabled, serverset primary port must be specified.'
        )
        assert isinstance(
            options.serverset_module_extra,
            dict), ('Serverset additional endpoints must be a dictionary!')
        for name, value in options.serverset_module_extra.items():
            assert isinstance(
                name, str), 'Additional endpoints must be named by strings!'
            assert isinstance(
                value, int), 'Additional endpoint ports must be integers!'

        try:
            primary_port = int(options.serverset_module_primary_port)
        except ValueError as e:
            raise ValueError('Could not parse serverset primary port: %s' % e)

    def _construct_serverset(self, options):
        import socket
        import threading
        import zookeeper
        from twitter.common.zookeeper.client import ZooKeeper
        from twitter.common.zookeeper.serverset import Endpoint, ServerSet
        log.debug('ServerSet module constructing serverset.')

        hostname = socket.gethostname()
        primary_port = int(options.serverset_module_primary_port)
        primary = Endpoint(hostname, primary_port)
        additional = dict((port_name, Endpoint(hostname, port_number))
                          for port_name, port_number in
                          options.serverset_module_extra.items())

        # TODO(wickman) Add timeout parameterization here.
        self._zookeeper = ZooKeeper(options.serverset_module_ensemble)
        self._serverset = ServerSet(self._zookeeper,
                                    options.serverset_module_path)
        self._join_args = (primary, additional)
        self._join_kwargs = ({
            'shard': options.serverset_module_shard_id
        } if options.serverset_module_shard_id else {})

    def _join(self):
        log.debug('ServerSet module joining serverset.')
        primary, additional = self._join_args
        self._membership = self._serverset.join(
            primary,
            additional,
            expire_callback=self.on_expiration,
            **self._join_kwargs)

    def on_expiration(self):
        if self._torndown:
            return

        log.debug('Serverset session expired.')
        if not app.get_options().serverset_module_persistence:
            log.debug('Committing seppuku...')
            sys.exit(1)
        else:
            log.debug('Rejoining...')

        self._rejoin_event.set()

    def setup_function(self):
        options = app.get_options()
        if options.serverset_module_enable:
            self._assert_valid_inputs(options)
            self._construct_serverset(options)
            self._thread = ServerSetJoinThread(self._rejoin_event, self._join)
            self._thread.start()
            self._rejoin_event.set()

    def teardown_function(self):
        self._torndown = True
        if self._membership:
            self._serverset.cancel(self._membership)
            self._zookeeper.stop()