From @sbhhbs on Tue Jan 09 2018 02:49:06 GMT+0000 (UTC)
The use case is for example:
- the service it self requires a stable hashing, so that, for example, i can routine all traffic of the same user id to the same physical machine’s service instance.
- I have a service that is updated, and like to update one service instance to test it. So I can select some user in whitelist and make their traffic always goes to the updated service instance.
My idea is when specify the service, I can always add some tags on it. And when calling the service, i can control if I’d like a service’s with that tag.
Or, is their any way to get a list of existing instances of a service, so that I can call that instance directly?
Copied from original issue: https://github.com/nameko/nameko/issues/500
From @mattbennett on Wed Jan 10 2018 11:02:39 GMT+0000 (UTC)
You can’t do this with the built-in RPC implementation because of the way the message routing is configured. All service instances consume from a single queue and are therefore indistinguishable.
The routing is as follows:
MESSAGE ROUTING KEY EXCHANGE BINDING QUEUE CONSUMERS
nameko-rpc +----------------+
+---+ +-----------------------------+ +------>service instance|
+-+ |X X| | | | +----------------+
|X| +----------------------------> | X +-------------------> {service-name} +------+
+-+ {service-name}.{method-name} |X X| {service-name}.* | | | +----------------+
+---+ +-----------------------------+ +------>service instance|
+----------------+
In words:
- Messages are published to the
nameko-rpc
exchange…
- With a routing key describing the target service and method name
- One queue per service is bound to the (topic) RPC exchange with a wildcard binding matching the service name and any method name
- Therefore all request messages for a target service will be deposited into the queue for that service
- Finally all instances of the target service consume from the service queue. Messages are consumed in a round-robin.
Hopefully that illustrates why targeting service instances isn’t possible.
You could get your desired behaviour by using a different routing topology. Something like this:
MESSAGE ROUTING KEY EXCHANGE BINDING QUEUE CONSUMERS
nameko-rpc
+---+ +-----------------------------+
+-+ |X X| | | +----------------+
|X| +----------------------------------> | X +------------------------> {service-name}-foo +-------->service instance| Tags: foo
+-+ {service-name}.{method-name}.{tag} |X X| {service-name}.*.foo | | +----------------+
+---+-+ +-----------------------------+-+
+-+ +-+
+-+ +-----------------------------+ +-+
+-+ | | +-->----------------+
+----------------> {service-name}-bar +-------->service instance| Tags: foo, bar
{service-name}.*.bar | | +----------------+
+-----------------------------+
This could be implemented as a custom extension that extended the built-in ones.