Monday 4 April 2016

Micro Services - Spring Boot, Eureka and Feign - Part 2

In the last post I set up a very basic 'Hello World' Spring Boot REST service running on an EC2 instance. One of the corner stones of Micro Services and Spring Boot is auto discovery of services from a client. In this post I will demonstrate the use of Eureka and Feign to register the Hello Service and automatically discover and call it from a client. Eureka, created by Netflix, runs in the same environment as the micro services. You are likely to want multiple environments - Dev, Test, Production, each with a different set of the services and end points. In a cloud environment, those services and their end points are transient. You may well be spinning up and tearing down instances many times a day in Dev. In production, you may well be autoscaling services across multiple availability zones. The importance of self registering services and auto discovery is evident.

  1. The Spring Boot Hello Service is modified to register itself with another Spring Boot application configured as a Eureka server.
  2. Another Spring Boot app, which implements the Feign client to call the Hello Service, queries the Eureka server asking for the end point of the Hello Service. 
  3. Eureka returns the details of the Hello Service to the client.
  4. The client makes requests to the Hello Service without any prior knowledge as to its whereabouts.

Create the Eureka Server


First of all we'll create and launch the Eureka server in the same environment our Hello Service is running. In a Dev environment we'll probably just want one single Eureka instance but in Production we will want some kind resilience. Eureka handles this with the ability to replicate the service across availability zones. For the purposes of simplicity I won't be covering that in this blog and will just set up a single Eureka instance in a single availability zone.

Eureka is itself run as a simple Spring Boot application. Again, we'll start with the pom.xml and import into an IDE. As with the Hello Service; the key is the parent. This gives us everything we need. This time, I will also pull in the Spring Cloud pom which is a parent of the Eureka server I will implement within the application.

Import this into the IDE, set up a simple package structure and create a class with a main method. This is pretty much exactly the same as our Application class from the Hello service although this time we add the EnableEurekaServer annotation.

As with our previous Spring Boot example I can add an application.properties file to the classpath which contains any custom configuration I require. By default the Eureka server will attempt to register itself as a service. It's a simple case to turn that off. I've also added some logging configuration to quiet things down a bit and specified a point through which services and clients will 'talk' to the Eureka service.
And that is it!!!!! Spin up another micro instance, deploy the build and execute it as before. One thing to note is that you'll need to ensure your security groups and VPC subnet configuration allows the Hello Service and Eureka instances to communicate. Obviously, there are many ways to set this up and you'll probably have your own security configuration. As this is just a Dev example, I launched my instances into the same subnet and opened up 8761 to any other instance with the same security group association.

Register the Hello Service with Eureka


Now we'll edit the Hello Service from the previous article and make it register itself with Eureka so that clients can discover its location. To do this we must enable the application as a Eureka Discovery Client with another annotation. Currently, our Hello Service app only has a dependency on Spring Boot. We need to reimport the build file and add a dependency on Spring Cloud and Eureka.

We can add the annotation to the Hello Service Application class telling it to register with Eureka.

By default, the Eureka client will attempt to locate Eureka on localhost. We need to tell it to find Eureka on the instance we are running it on. Depending on your AWS set up you may add the private ip, Elastic ip or domain as a property to the application.properties file in the Hello Service classpath.
As you can see, there's an additional configuration to tell Eureka to register the Hello Service by IP address. By default, Eureka will register the machine name. On AWS that's the instance ID. We could force Eureka to register the service with a configured value such as a load balancer or Route 53 domain. As this is only a basic example and the service, client and Eureka server are all in the same subnet, the private IP address of the Hello Service will do.

Start the Eureka and then redeploy and reboot the Hello Service. Watch the logs, you'll see the Hello Service start and after a few seconds it will report a successful registration with Eureka. We can now open a browser and point it at Eureka. This will present us with the management UI and show our Hello Service as the only registered service along with the IP address where the end point can be found.

Eureka UI showing the Hello Service with registered IP address (blurred)

Create a Hello Service Client 

Now the Hello Service is registered with Eureka we can create a client which will call the Hello Service without having any prior knowledge of its whereabouts. To do this we will again use Spring Boot, Spring Cloud and also Feign which will discover the Hello Service end point from Eureka. Once again we'll create a simple Spring Boot project starting with the pom.xml below

Once imported created another Application class, annotated as a SpringBootApplication. We also annotate this class to tell Spring it's a Eureka and Feign client.

We now need to create two more Java types to enable the application to make a call to the Hello Service. First of all, create an interface annotated as a FeignClient. This interface has one method for each service end point or operation, annotated with a RequestMapping bind. This might not seem so obvious because a RequestMapping annotation might more commonly be found on a controller. The presence of this annotation might make you think it is serving the mapping but it simply binds it to the method. Feign understands this and knows to route calls to the method to the remote Hello Service, at the end point discovered from Eureka with the path and mapping described in the annotation. The FeignClient annotation has a value of the name of the service we want to call. Our Hello Service application is named hello-service and we can see the name in the Eureka registry. using this name, Feign will contact Eureka and discover the end point IP address.

We now need a runnable class, Spring Boot supplies the CommandLineRunner stereotype which enforces implementation of a run method. This is called following successful initialization of the Spring Boot application. Our CommandLineRunner implementation simply calls the HelloClient method so that, in this example, the web service call to HelloService is made once on boot up.

Lastly, we just need to the application.properties on the classpath. The only configuration we need is to tell the application the location of Eureka server which the EnableEurekaClient annotation will pick up and use.

Nice and simple! If you like, you can build and deploy this and run it in the same way as the other two Spring Boot apps or just run the main method from your IDE. You should see the Client application boot up, contact Eureka, discover the Hello Service end point and call it, which will return the Hello World message. All accomplished without any pre configured address information of the Hello Service itself.

Micro Services - Spring Boot, Eureka and Feign - Part 1

Micro Services


The term 'Micro Service' is the current flavour of the month within software circles. However, this approach to architecture; splitting up applications into small units of functionality is nothing new. As developers and architects we always look to decouple our systems into single, simple units of functionality. This is a basic principle of OO. The philosophy of Micro Services is to decouple units of functionality entirely. Each unit should effectively standalone in its own environment with as little, or no, dependency on others. Again, this isn't a new approach. Since the advent of web services, inparticular REST, we have decoupled our systems into simple, stateless, independently scalable applications. The advantages of this are clear but as our systems grow into transient environments it becomes difficult for each application to keep track on service end points of other systems. The big win of the Micro Service approach is automatic discovery which helps DevOps solve the headache of configuration across the ecosystem.

In part 1 of this blog I will use Spring Boot to set up a Micro Service very quickly and easily and run it in the cloud. In part 2 I will configure this service to register itself for auto discovery and create a client which has no configuration dependency on the service. This is accomplished with Spring Cloud, Netflix Eureka and Feign; three important frameworks which make up the basis of Spring's Micro Service implementation.

Creating a Micro Service with Spring Boot


Spring Boot allows us to create a deployable application at the drop of a hat. There's no need for a external web server or servlet container, Spring Boot takes care of all that and allows us to just execute a jar file to run a web service. Spring Boot employs the common Spring philosophy of convention over configuration, often to the extreme. This results in an annotation rich framework with little, or no, xml or properties to configure.

To demonstrate this we'll start with a simple REST service which will return a 'hello world' string to a GET request. As with all applications, start with the Maven build file - pom.xml and import into your favorite IDE.

The key here is the parent - spring-boot-starter-parent. This brings in all the dependencies and environment configuration you need to run a Spring Boot app. The only additional dependencies I've added are the web and test packages because this application will be a web app for which I want to write some unit tests. Once imported, create a package structure and add a class name 'Application' with a main method.

By default, the SpringBootApplication annotation enables component scan for its own and sub packages. Therefore, it is convention to add our other components to packages below this one. Create a web and service package for our MVC controller and service layer classes.




The MVC controller and service are both very simple as you'd imagine. Amongst other things, Spring Boot includes automatic configuration of Spring MVC, which is again enabled by the SpringBootApplication annotation. This means its a simple case of just annotating the controller as a RestController and adding the mappings. The HelloService simply returns a string saying hello

That pretty much concludes the service. The only other addition is a properties file. By default, Spring Boot will look for a file named application.properties on the root classpath. This file will hold any other configurations which are required in subsequent parts of this blog. For now, we just add a name for the service, like so.
To run the application as a web service we need an environment hosting the JDK 1.8. No application server is required as Spring Boot has an embedded pre-configured tomcat. If you have an AWS account, spin up a micro instance, ensure you are running Java 1.8 and add the following line as user data to run the HelloService
Open a browser and navigate to the instance on the default 8080 tomcat port. The browser, by default, will issue a GET request and return the message from the service.