Versioning apis


#1

Hi,
How do you use versioning of apis in nameko? I used headers in rabbit to restrict a service only to respond to calls for it's own version, and used urls in http paths with similar intent. What are your best practices with nameko?

Thanks for sharing!
Remco


#2

Unless I'm mistaken, using a header means that a service must consume the
message before it can tell whether or not it supports a compatible version.
It would be better to use different queues for each version and only attach
consumers to the appropriate queues. That has the additional benefit of
giving you visibility into the traffic to each version (by inspecting
rabbit queues).

As for best practices... At Student.com we have a versioned API layer
outside the "core" services. We could write a whole series of blog posts on
this but the basic structure is as follows:

We have two classifications of services: domain services and facades.
Domain services encapsulate core business logic (as in Domain Driven
Design) and facades aggregate the domains for a specific customer. For
example, we have a "mobile-facade" that contains all the APIs used to drive
our mobile apps.

Facade APIs use HTTP, are explicitly versioned and form our contract with
the specific customer. Domain service APIs use RPC and not explicitly
versioned. Each domain service release maintains backwards compatibility
with the previous one, which is verified by checking that the facade
contracts can all still be satisfied.

This structure is nice for a few reasons:

1. The facade service APIs are a well-defined contract between us and our
customers
2. We have explicit versions without having to test the explosive
combinatorials of M services with N different versions
3. We're free to deploy domain services continuously as long as all the
currently supported facade contracts are satisfied

Hope that helps!

Matt.

···

On Friday, March 4, 2016 at 9:46:56 PM UTC, remco....@gmail.com wrote:

Hi,
How do you use versioning of apis in nameko? I used headers in rabbit to
restrict a service only to respond to calls for it's own version, and used
urls in http paths with similar intent. What are your best practices with
nameko?

Thanks for sharing!
Remco


Domain Driven Design & Nameko
#3

Good explanation. Thanks for sharing. You are right about the message
headers. My lib wouldn't accept a message of the wrong version so rabbit
would issue it to whatever next is listening to handle the same message.
Not perfect, but doable if you don't have a lot of version simultaneously,
and not a lot of listeners. Using nameko, wouldn't it be easier to name a
service with a version number? It would solve all the shuffling with the
queues right?

I like layered api's style at student.com. One internal and one external.
Guess I will have to read up on domain driven design. Those benefits are
definitely appreciated!

···

Op zondag 6 maart 2016 14:05:30 UTC+1 schreef Matt Bennett:

Unless I'm mistaken, using a header means that a service must consume the
message before it can tell whether or not it supports a compatible version.
It would be better to use different queues for each version and only attach
consumers to the appropriate queues. That has the additional benefit of
giving you visibility into the traffic to each version (by inspecting
rabbit queues).

As for best practices... At Student.com we have a versioned API layer
outside the "core" services. We could write a whole series of blog posts on
this but the basic structure is as follows:

We have two classifications of services: domain services and facades.
Domain services encapsulate core business logic (as in Domain Driven
Design) and facades aggregate the domains for a specific customer. For
example, we have a "mobile-facade" that contains all the APIs used to drive
our mobile apps.

Facade APIs use HTTP, are explicitly versioned and form our contract with
the specific customer. Domain service APIs use RPC and not explicitly
versioned. Each domain service release maintains backwards compatibility
with the previous one, which is verified by checking that the facade
contracts can all still be satisfied.

This structure is nice for a few reasons:

1. The facade service APIs are a well-defined contract between us and our
customers
2. We have explicit versions without having to test the explosive
combinatorials of M services with N different versions
3. We're free to deploy domain services continuously as long as all the
currently supported facade contracts are satisfied

Hope that helps!

Matt.

On Friday, March 4, 2016 at 9:46:56 PM UTC, remco....@gmail.com wrote:

Hi,
How do you use versioning of apis in nameko? I used headers in rabbit to
restrict a service only to respond to calls for it's own version, and used
urls in http paths with similar intent. What are your best practices with
nameko?

Thanks for sharing!
Remco


#4

Ah yes, of course -- putting the version number in the service name would
be a very simple solution!

Since nameko services are regular Python classes you can make use of
inheritance too, only overriding the parts that need to change between
versions.

···

On Thursday, March 10, 2016 at 2:14:06 PM UTC, remco....@gmail.com wrote:

Good explanation. Thanks for sharing. You are right about the message
headers. My lib wouldn't accept a message of the wrong version so rabbit
would issue it to whatever next is listening to handle the same message.
Not perfect, but doable if you don't have a lot of version simultaneously,
and not a lot of listeners. Using nameko, wouldn't it be easier to name a
service with a version number? It would solve all the shuffling with the
queues right?

I like layered api's style at student.com. One internal and one external.
Guess I will have to read up on domain driven design. Those benefits are
definitely appreciated!

Op zondag 6 maart 2016 14:05:30 UTC+1 schreef Matt Bennett:

Unless I'm mistaken, using a header means that a service must consume the
message before it can tell whether or not it supports a compatible version.
It would be better to use different queues for each version and only attach
consumers to the appropriate queues. That has the additional benefit of
giving you visibility into the traffic to each version (by inspecting
rabbit queues).

As for best practices... At Student.com we have a versioned API layer
outside the "core" services. We could write a whole series of blog posts on
this but the basic structure is as follows:

We have two classifications of services: domain services and facades.
Domain services encapsulate core business logic (as in Domain Driven
Design) and facades aggregate the domains for a specific customer. For
example, we have a "mobile-facade" that contains all the APIs used to drive
our mobile apps.

Facade APIs use HTTP, are explicitly versioned and form our contract with
the specific customer. Domain service APIs use RPC and not explicitly
versioned. Each domain service release maintains backwards compatibility
with the previous one, which is verified by checking that the facade
contracts can all still be satisfied.

This structure is nice for a few reasons:

1. The facade service APIs are a well-defined contract between us and our
customers
2. We have explicit versions without having to test the explosive
combinatorials of M services with N different versions
3. We're free to deploy domain services continuously as long as all the
currently supported facade contracts are satisfied

Hope that helps!

Matt.

On Friday, March 4, 2016 at 9:46:56 PM UTC, remco....@gmail.com wrote:

Hi,
How do you use versioning of apis in nameko? I used headers in rabbit to
restrict a service only to respond to calls for it's own version, and used
urls in http paths with similar intent. What are your best practices with
nameko?

Thanks for sharing!
Remco


#5

Thanks for that idea! Inheritance with multiple versions at once. Though
Sam Newman of "Building Microservices" clearly is not in favor of the
solution, it seems to be a very easy one to implement.

···

Op donderdag 10 maart 2016 22:31:24 UTC+1 schreef Matt Bennett:

Ah yes, of course -- putting the version number in the service name would
be a very simple solution!

Since nameko services are regular Python classes you can make use of
inheritance too, only overriding the parts that need to change between
versions.

On Thursday, March 10, 2016 at 2:14:06 PM UTC, remco....@gmail.com wrote:

Good explanation. Thanks for sharing. You are right about the message
headers. My lib wouldn't accept a message of the wrong version so rabbit
would issue it to whatever next is listening to handle the same message.
Not perfect, but doable if you don't have a lot of version simultaneously,
and not a lot of listeners. Using nameko, wouldn't it be easier to name a
service with a version number? It would solve all the shuffling with the
queues right?

I like layered api's style at student.com. One internal and one
external. Guess I will have to read up on domain driven design. Those
benefits are definitely appreciated!

Op zondag 6 maart 2016 14:05:30 UTC+1 schreef Matt Bennett:

Unless I'm mistaken, using a header means that a service must consume
the message before it can tell whether or not it supports a compatible
version. It would be better to use different queues for each version and
only attach consumers to the appropriate queues. That has the additional
benefit of giving you visibility into the traffic to each version (by
inspecting rabbit queues).

As for best practices... At Student.com we have a versioned API layer
outside the "core" services. We could write a whole series of blog posts on
this but the basic structure is as follows:

We have two classifications of services: domain services and facades.
Domain services encapsulate core business logic (as in Domain Driven
Design) and facades aggregate the domains for a specific customer. For
example, we have a "mobile-facade" that contains all the APIs used to drive
our mobile apps.

Facade APIs use HTTP, are explicitly versioned and form our contract
with the specific customer. Domain service APIs use RPC and not explicitly
versioned. Each domain service release maintains backwards compatibility
with the previous one, which is verified by checking that the facade
contracts can all still be satisfied.

This structure is nice for a few reasons:

1. The facade service APIs are a well-defined contract between us and
our customers
2. We have explicit versions without having to test the explosive
combinatorials of M services with N different versions
3. We're free to deploy domain services continuously as long as all the
currently supported facade contracts are satisfied

Hope that helps!

Matt.

On Friday, March 4, 2016 at 9:46:56 PM UTC, remco....@gmail.com wrote:

Hi,
How do you use versioning of apis in nameko? I used headers in rabbit
to restrict a service only to respond to calls for it's own version, and
used urls in http paths with similar intent. What are your best practices
with nameko?

Thanks for sharing!
Remco