Introduction
Hey guys,
this week’s post is about Microservices created with the various Spring Cloud frameworks and how to include services written in non-JVM programming languages into the Spring Cloud ecosystem using Spring Cloud Netflix Sidecar. Please be aware that this tutorial is specifically written for people who know the architectural style of Microservices and are creating applications using the various Spring Cloud frameworks or plan to do so.
If you don’t know what Microservices are, please read the excellent blog post from Martin Fowler regarding Microservices. Basically every book, article or scientific paper (and my bachelor thesis) about this architectural style is based on this blog post, so yeah, it’s a pretty good read.
The problem I faced
I am currently in the process of writing my bachelor thesis and therefore implemented a prototypical application using the Microservice architectural style. Because I’m a Java guy and know the Spring framework, I decided to implement the application using the Spring Cloud ecosystem. I use an Eureka server as a service registry. Furthermore, I implemented several Spring Boot services and was able to register them to Eureka with the use of an annotation and a little bit of configuration.
It turned out that I had to implement one of the services making up my application with PHP (yikes!) because a library I had to use is not available in Java. Because I only had two weeks for the implementation of my prototype I certainly wouldn’t have been able to write a Java implementation of the library. Therefore I decided to create a PHP microservice with the help of Lumen.
Furthermore I didn’t want to miss out on the fancy features of my service registry like client-side load-balancing and the decoupling of my service providers from my consumers. After a bit of research I found the documentation of the Eureka HTTP API. I got discouraged at the sight of the XSD I had to implement in my PHP service to register it with Eureka. I really did not want to implement the various REST operations manually into my service because my PHP knowledge is very limited and I have never used Lumen before.
I was on the verge of giving up when I found Spring Cloud Netflix Sidecar. It promised to let me register my service written in PHP with Eureka using one annotation and a little configuration, just like in my other services written with Spring boot.
Spring Cloud Netflix Sidecar
Spring Cloud Netflix Sidecar is a subproject of Spring Cloud Netflix and is inspired by the Netflix Prana project. A sidecar service is basically yet another Spring boot application that runs on the same host as your non-JVM service. It registers itself to your service registry with a defined application name and frequently checks the health of your non-JVM service via a REST call. The sidecar is also able to forward calls from other services of your application. By using a sidecar application you only have to implement minimal changes to your non-JVM application, so it’s also great for legacy projects.
A working example
For you to get the hang of Spring Cloud Netflix Sidecar I created a very minimalistic project consisting of a Eureka server, a Lumen service capable of doing nothing and the corresponding sidecar application. You have to have docker and docker-compose installed to run this example. In order to run the example application, clone the project from our GitHub repository. After that change into its directory and typedocker-compose up -d
into your console. This command pulls all necessary images from our DockerHub registries and starts the containers. After everything has started, you can access http://localhost:8761/, which is the Eureka dashboard, and see the lumen service registered.
You can stop the container containing the lumen service by typing docker stop *lumen-service*
and the status of the application on your Eureka dashboard should change to DOWN a few seconds later. That is because the sidecar application’s heartbeats are not answered by your lumen service, obviously.
How to set this up
Sadly, sidecar isn’t available in Spring Initializr, so you have to manually add following maven dependency to your Spring Boot application:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-sidecar</artifactId>
</dependency>
After adding the dependency you can annotate your main class with the @EnableSidecar
annotation.
It would not be a proper Spring application if you wouldn’t have to create an application.yml and add all the necessary configuration, so let’s do this.
server:
port: 5678
spring:
application:
name: lumen-service
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URI:http://localhost:8761/eureka}
instance:
preferIpAddress: true
sidecar:
port: ${SIDECAR_PORT:8000}
health-uri: ${SIDECAR_HEALTH_URI:http://localhost:8000/health}
We have to tell the sidecar application on which port to run and what it’s name is. Note that the spring.application.name
property is the one getting displayed on your Eureka dashboard. Furthermore we have to tell the application where the registry server is located.
The important configuration are the
- sidecar.port: This is the port your non-JVM application is listening on.
- sidecar.health-uri: This is the REST endpoint of your non-JVM where you implemented a health check.
The configured health check REST endpoint should return a JSON document looking like this:
{
"status": "UP"
}
Implementing such a simple health check in Lumen is pretty easy, just add the following code snippet in your web.php located in the routes folder of your project:
$router->group(['prefix' => 'health'], function () use ($router) {
$router->get('', function () {
return response()->json(['status' => 'UP'])
});
});
And that’s all you have to change in your non-JVM application to get all the advantages of the Spring Cloud ecosystem.
Roundup
In this post I showed you how to include a non-JVM application in your Spring Cloud ecosystem. This can be done by creating a Spring boot application with the sidecar dependency and some configuration and adding a simple health check to your service.
I hope I was able to help some people with this post!
Best regards
Leon