This post will be included in a chapter from a forthcoming book Building Microservices for the Cloud, A guide for busy Java developers I'm writing. If you enter your email address here, I'll send you the previous chapters as well as each new chapter when it gets published!
1. MULTI-VERSION SERVICE DISCOVERY USING SPRING CLOUD NETFLIX EUREKA AND RIBBON
As services evolve over time, changes are made to the domain that very-likely require API versioning to prevent breaking backwards compatibility.
Unless you work in a very controlled environment, for instance, where it’s known that client applications are also distributed with the API services and there is no possibility of an old client using newer API services deployment, I’m a firm believer you should never break backwards compatibility.
I’ll say it again because this is very important, you should never break backwards compatibility, if you do, customers and partners get very angry and fixing it afterwards normally requires more effort than versioning from the beginning.
This is a simple Spring Boot application which implements two versions of the same endpoint and registers both versions with a Eureka server instance.
This command will create a Maven project in a folder named demo-multiversion-registration-api-1 with most of the dependencies used in the accompanying source code.
This is the name the service will use to register with Eureka.
This file includes Eureka-related configuration settings, already explained here.
The interesting part is the Spring profiles, where a new metadata (key, value) pair is added to each profile. These (key, value) pairs make to Eureka through the registration process and will be used by Demo Service 2 to filter out service instances.
This is the application entry point telling the Spring container to scan com.asimio.api.multiversion.demo1.rest package for @Component or derivate annotations.
The resources implementation details doesn’t matter, just that ...v1.Actor and ...v2.Actor classes are different either in the number of attributes or their names.
Lets start a Eureka instance and Demo Service 1 and take a look at its registration metadata.
4. RUNNING THE EUREKA SERVER
Available in the source code section, the Eureka server could be downloaded, built and started as:
Also available in the source code area, let’s start two instances, each corresponding to a different Spring profile:
Once registered with the Eureka server, demo-multiversion-registration-api-1 metadata looks like:
Notice in line the presence of <versions>v1</versions> and <versions>v1,v2</versions> elements which corresponds with the new metadata added in Demo Service 1’s applicataion.yml.
6. CREATE THE DEMO SERVICE 2
Demo Service 2 is also a simple Spring Boot application exposing two endpoints and acting as a client of Demo Service 1 to demonstrate sending requests to different API versions.
Creating it is similar to Demo Service 1 creation but changing baseDir and artifactId parameters:
Two Ribbon clients are defined with ids: demo-multiversion-registration-api1-v1 and demo-multiversion-registration-api1-v2. Both target the same service: demo-multiversion-registration-api-1 via service discovery using Eureka.
Similarly to Demo Service 1’s Application.java, this is the application’s entry point also indicating the Spring IoC container to scan com.asimio.api.multiversion.demo2.config and com.asimio.api.multiversion.demo2.rest packages for @Component-related annotations.
This class instantiates the RestTemplate bean to send requests to Demo Service 1. @LoadBalanced indicates this RestTemplate instance will use a Ribbon client as the internal HTTP client to send requests.
It also defines two Ribbon clients where the names match the client keys found in Demo Service 2’s application.yml and configured by @RibbonClientconfiguration’s value.
This is the first Ribbon client configuration implementation. It provides a specific ServerListFilter bean, reviewed here, but it could have also provided other beans such as implementation of:
Spring CloudNetflix creates an ApplicationContext for each Ribbon client and configures the client components with these beans.
RibbonConfigDemoApi1V2.java is similar to RibbonConfigDemoApi1V1.java but using enum DEMO_REGISTRATION_API1_V2.
A enum with service and version information. demo-multiversion-registration-api-1 is the service name found in the Eureka registry.
Notice "lastName":"8601" and "lastName":"8602", it means both Demo Service 1 instances are being load-balanced.
Let’s send a requests to v2:
The Demo Service 1 instance listening on 8602 is the only one servicing v2. Once it gets shutdown requests fail as follow:
That’s all for this post. Thanks for reading and feedback is always appreciated. If you found this post helpful and would like to receive updates when content like this gets published, sign up to the newsletter.
8. SOURCE CODE
Accompanying source code for this blog post can be found at: