I am getting started with Spring Cloud using Eureka and Zuul and had some questions around structuring blue/green and Canary deployments. So far, I have the basics worked out and have Eureka, Zuul, and a config server working as expected. What I am trying to accomplish is set up a service that has two versions, say 1.0 and a 1.1. For a subset of specific users, I want to route them to the 1.1 version and everyone else should go to the 1.0 version.
The Zuul filter API is a little light on documentation and I'm struggling a bit to grok some of the concepts, so I thought I'd ask a few questions here. I have also have some basic filters running, which don't do a whole lot a the moment other than getting the identity of the principal and the service they are requesting. Where I am hitting a wall is understanding how to expose two different versions of the same service to Eureka and Zuul. A few things I'm curious about:
/simpleservice
do I expose two different serviceIDs (i.e. simpleservice
and simpleservice-1.1
)? And If I do that, when one of the targeted users requests /simpleservice
, I'm having Zuul send them to /simpleservice-1.1
Zuul is built on servlet 2.5 (works with 3. x), using blocking APIs. It doesn't support any long lived connections, like websockets. Gateway is built on Spring Framework 5, Project Reactor and Spring Boot 2 using non-blocking APIs.
The new version of the Zuul gateway is built on top of the Netty server, and includes some improvements and new features. You can read more about them on the Netflix blog. Despite this decision being made by the Netflix cloud team, the Spring Cloud team has abandoned development of the Zuul module.
Zuul acts as the API gateway, providing a uniform, single point of entry into the set of microservices, while Eureka is essentially used as a “meta data” transport. Each client application instance (read microservice) registers its instance information (location, port, etc.)
Assuming you are using Ribbon as well, I would leave the service IDs as they are. Instead I would take a look at the com.netflix.loadbalancer
package. Canary deployments are essentially load balancing with very specific constraints. You could implement your own AbstractLoadBalancerRule
that picks servers based on some property you would like to base the routing on. Then add that rule to the configuration of your Zuul instance.
@Configuration
public class CanaryConfiguration {
@Bean public IRule canaryDeploymentRule(IClientConfig config) {
CanaryDeploymentRule rule = new CanaryDeploymentRule ();
rule.initWithNiwsConfig(config);
return rule;
}
}
If you let your services register themselves in Eureka with different service IDs ("simpleservice" and "simpleservice-x.y"), I suppose things are bound to become complicated. You would have to extend the discovery client to ignore the version part ("-x.y", while still being able to deal with "foo-service") when retrieving the list of available servers from Eureka and then do some selection process to pick the right one anyway. So I guess things would just become more complex.
This is all based on best guesses, I haven't actually implemented this. I realize that this question is almost 4 months old. So if you have found some other solution in the meantime, it would be great if you could share it in an answer to your own question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With