Hystrix / Monitor Dashboard and Turbine

Before we start

Hello everyone, first of all, for those that eventually are following the serie, sorry about this huge delay between one post and another, I will avoid this from now on. However, if you hit this page without following the Step-by-step into Micro-Services Architecture with Spring and Netflix OSS, it can be useful to know about the serie:

Our subject today is one of the most awesome that we’ll talk about in the serie and it demands pretty basic coding – nevertheless, the results are pretty visuals, very useful and helps us to build a resilient, feasible and reliable system.

Circuit Breaking

Well, you can be one of those guys that are always suspicious, lets say, do you always smell a rat with this “thing” of various microservices running separate and wondering about a tragic scenario?

If your answer to this question is “No, I’m not this guy.” I’d like to suggest that you should reconsider: we know that sometimes bad things just happen and the consequences can be irrecoverable (from lose money, loss of confidence or depending on the scope of your system, why not say – causing injury to people).

Thinking about it, our friend’s blog, Magnus Larsson stated some interesting phrase about chain of failures:

A chain of failures, where an error in one component can cause errors to occur in other components that depend on the failing component. This needs special attention in a microservice based system landscape where, potentially a large number of, separately deployed microservices communicate with each other. One common solution to this problem is to apply a circuit breaker pattern.

Given this, to know more about Circuit Breaker pattern, it is valid to listen from someone well-known inside Computer Science community – for me Martin Fowler has the credibility need to talk about all subjects ๐Ÿ˜€ – see here what he said on his blog:

The basic idea behind the circuit breaker is very simple. You wrap a protected function call in a circuit breaker object, which monitors for failures. Once the failures reach a certain threshold, the circuit breaker trips, and all further calls to the circuit breaker return with an error, without the protected call being made at all. Usually you’ll also want some kind of monitor alert if the circuit breaker trips.

Hystrix / Monitor Dashboard and Turbine

With these substantial foundations, the Netflix team created Hystrix a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.

68747470733a2f2f6e6574666c69782e6769746875622e636f6d2f487973747269782f696d616765732f687973747269782d6c6f676f2d7461676c696e652d3835302e706e67

The funny part is that the configuration / code demanded to make it works is very simple, we are going to see in a minute.

To finalize the theoretical part, as HystrixCommands and HystrixObservableCommands execute they generate metrics on execution outcomes and latency. These are very useful to operators of the system, as they give a great deal of insight into how the system is behaving. Hystrix offers metrics per command key and to very fine granularities (on the order of seconds). Exposed this, we will also be able to make use of these outcomes from Hystrix to enhance our tool set and extract profitable information of them. To do so, we will aggregate these metrics individually on a stream and show through a dashboard – here enter both: Monitor Dashboard and Turbine. We’ll get there, don’t worry. Monitor + Turbine:

NetflixDash

Hands on

Info: Hystrix uses RabbitMQ to communicate between circuit breakers and dashboards, in order to our examples work, we need to barely configure our local environment to have it installed. We’ll do it quickly.

Access https://www.rabbitmq.com/download.html and download the corresponding version according to your system:

Screenshot from 2016-04-29 16:00:57

Once you have downloaded and installed, run something like: sudo rabbitmqctl status

Screenshot from 2016-04-29 16:07:30

You can use rabbitmqctl status to verify whether a broker is running.
Now, we need to enable a specific feature of Rabbit: the rabbitmq-management plugin, thatย  provides an HTTP-based API for management and monitoring of your RabbitMQ server, along with a browser-based UI and a command line tool, rabbitmqadmin. Features include:

  • Declare, list and delete exchanges, queues, bindings, users, virtual hosts and permissions.
  • Monitor queue length, message rates globally and per channel, data rates per connection, etc.
  • Send and receive messages.
  • Monitor Erlang processes, file descriptors, memory use.
  • Export / import object definitions to JSON.
  • Force close connections, purge queues.

Here the commands to enable the plugin management:

fernando@fernando-Vostro-5470:~$ sudo rabbitmq-plugins enable rabbitmq_management
The following plugins have been enabled:
mochiweb
webmachine
rabbitmq_web_dispatch
amqp_client
rabbitmq_management_agent
rabbitmq_management

Applying plugin configuration to rabbit@fernando-Vostro-5470... started 6 plugins.

 

After it is done, you can access: http://localhost:15672/ with user and pass: guest.

Screenshot from 2016-04-29 16:17:23

The console admin for RabbitMQ seems like this:

Screenshot from 2016-04-29 16:18:32.png

Obviously, in some moment you’ll have to restart your machine and don’t forget to run rabbitmq-server in case it is not set to start by default.


fernando@fernando-Vostro-5470:~$ sudo rabbitmq-server

RabbitMQ 3.6.1. Copyright (C) 2007-2016 Pivotal Software, Inc.
##  ##      Licensed under the MPL.  See http://www.rabbitmq.com/
##  ##
##########  Logs: /var/log/rabbitmq/rabbit@fernando-Vostro-5470.log
######  ##        /var/log/rabbitmq/rabbit@fernando-Vostro-5470-sasl.log
##########
Starting broker... completed with 6 plugins.


 

Now, lets focus on what interest to us, our Monitor Dashboard. For so, access http://start.spring.io and create a new project with the following configurations:

Create a new project:

Generate a: Maven Project
Spring Boot: 1.3.4
Group: com.spring.netflix.oss.microservices
Artifact: monitor-dashboard
Dependencies:
Cloud Bus AMQP, Hystrix Dashboard, AMQP, Config Client, Eureka Discovery, Web.

Screenshot from 2016-05-06 16:06:17.png

Later import the project into your IDE and as always we’ll edit the MonitorDashboardApplication.java reaching to enable a @EnableHystrixDashboard:

package com.spring.netflix.oss.microservices;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@SpringBootApplication
@EnableHystrixDashboard
@EnableDiscoveryClient
@Controller
public class MonitorDashboardApplication {

	public static void main(String[] args) {
		SpringApplication.run(MonitorDashboardApplication.class, args);
	}

	@RequestMapping("/")
	public String home() {
		return "forward:/hystrix";
	}
}

As always, delete the src/main/resources/application.properties and recreate it in a new fashion way: bootstrap.yml with the following content:

spring:
  application:
    name: monitor-dashboard
  cloud:
    config:
      uri: http://localhost:9090

This file is to say that our config will be managed by a config-server and we need to create a config-server/monitor-dashboard.yml in the specific project, i.e. microservices-config/MASTER/monitor-dashboard.yml. The result:

Screenshot from 2016-05-06 16:15:31

And the content of this file:

server:
  port: 8179

Simple, don’t you agree? For now, this part is done.

Newly, we talked about Turbine – it is our next module to build. Again we return to http://start.spring.io and set up a new project:

Generate a: Maven Project
Spring Boot: 1.3.4
Group: com.spring.netflix.oss.microservices
Artifact: turbine
Dependencies:
Config Client, Eureka Discovery, Web.

Note: Later will be necessary to edit the pom.xml manually adding new dependencies.

Screenshot from 2016-05-07 09:47:35.png

As soon as the project is generated and properly imported into IDE, open the pom.xml to add the needed dependencies. By the end, this pom will have the following structure:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.spring.netflix.oss.microservices</groupId>
	<artifactId>turbine</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>turbine</name>
	<description>Hystrix Dasboard</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.3.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			
			<exclusions>
		        <exclusion>
		            <groupId>org.springframework.boot</groupId>
		            <artifactId>spring-boot-starter-tomcat</artifactId>
		        </exclusion>
		    </exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-undertow</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-netflix-turbine-amqp</artifactId>
			<version>1.0.7.RELEASE</version>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Brixton.BUILD-SNAPSHOT</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
	
	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

</project>

Our main class also need adjusts to include :

package com.spring.netflix.oss.microservices;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.turbine.amqp.EnableTurbineAmqp;

@SpringBootApplication
@EnableTurbineAmqp
@EnableEurekaClient
public class TurbineApplication {

	public static void main(String[] args) {
		new SpringApplicationBuilder(TurbineApplication.class).run(args);
	}
}

Likewise the other modules, the configuration will look at config-server to obtain the ports, etc. To do so, remove the src/main/resources/application.properties and recreate it in a new fashion way: bootstrap.yml with the following content:

spring:
  application:
    name: turbine
  cloud:
    config:
      uri: http://localhost:9090

We need to create a microservices-config/MASTER/turbine.yml file. The content:

server:
  port: 0
turbine:
  amqp:
    port: 8989

Our example is almost complete now. However, any of this would make sense if we don’t have annotations with @HystrixCommand in our methods that must be protected against fails, that annotation will be our wizard that will enhance us with the possibility to extract information about the health of our services, i.e. whether our circuit is open or not, and also provide a fallback method.

The changes now will be done in our composite service that we created some posts ago. First of all, we’ll add some dependencies in our pom.xml, basically spring-cloud-starter-bus-amqp, spring-cloud-netflix-hystrix-amqp and spring-cloud-starter-hystrix. Instead of adding the full pom.xml here, if you need help to adequate yours, please, just access and copy this one:ย https://github.com/fernandoabcampos/spring-netflix-oss-microservices/blob/master/card-statement-composite/pom.xml

Once the dependencies are updated, we can edit CardStatementServiceController.java to add the annotation @HystrixCommand(fallbackMethod = “defaultCardStatementError”) and obviously, create this fallback method. The final result:

package com.spring.netflix.oss.microservices.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.spring.netflix.oss.microservices.model.CardVO;
import com.spring.netflix.oss.microservices.model.StatementVO;

@RestController
@RequestMapping("/api")
public class CardStatementServiceController {

	@Autowired
	CardClient cardClient;

	@Autowired
	StatementClient statementClient;

	@HystrixCommand(fallbackMethod = "defaultCardStatementError")
	@RequestMapping(value="/statement-by-card", method=RequestMethod.GET)
	public ResponseEntity<Map<CardVO, List<StatementVO>>>
	getStatementByCardId(@RequestParam Long cardId){
		Map<CardVO, List<StatementVO>> response = new HashMap<>();

		response.put(cardClient.getCard(cardId), statementClient.getStatements(cardId));

		return new ResponseEntity<Map<CardVO,List<StatementVO>>>(response, HttpStatus.OK);
	}

	public ResponseEntity<Map<CardVO, List<StatementVO>>>
	defaultCardStatementError(Long cardId){
		Map<CardVO, List<StatementVO>> response = new HashMap<>();
		return new ResponseEntity<Map<CardVO,List<StatementVO>>>(response, HttpStatus.OK);

	}
}

Well, it is all. Please, commit your configuration, push it to remote and later start the server in this sequence:

  1. Config-Server
  2. Discovery-Service
  3. {Edge-Server, Card-Service, Statement-Server, Card-Statement-Composite, Monitor-Dashboard and Turbine}

As soon as all is started, access: http://localhost:8179 just to see the main page of Hystrix Dashboard – the expected result is:Screenshot from 2016-04-30 20:14:10Then, provide a turbine stream (http://localhost:8989/turbine.stream) and click at “Monitor Stream”. Probably the Hystrix Dashboard will open another screen with some message like “Loading”. In another tab, invoke some calls against the controller that we enable Hystrix, for example: http://localhost:8765/card-statement-composite/api/statement-by-card?cardId=1 – press F5 some times just to force more than one call. It must result in:

Screenshot from 2016-05-05 21:44:14

Realize that all the circuits is closed (the system is answering well).

Now, to simulate an error, stop a service (as card-service) and continue doing subsequent calls to http://localhost:8765/card-statement-composite/api/statement-by-card?cardId=1. After some seconds, it will happen:

Screenshot from 2016-05-05 21:54:27

With this, we achieved our goal for now. Obviously, in a real world environment, we will create a fallback method more adequate than one that just return an empty list of records, however, the goal was to demonstrate how this pieces work together.

Thank you guys, see you in our next blog post.

Core Business Development – Card Service

Before we start

If you hit this page without following the Step-by-step into Micro-Services Architecture with Spring and Netflix OSS, it can be useful to know about the serie:

Part 4.1

Finally we arrived here, until now, we were preparing a layer of support services (and later we’ll create a set of more), but in this Part 4, as aforementioned at the beginning – where I’ve defined the scope of our project, that will be divided in 3 sub-chapters:

  1. Card-Service
  2. Statement-Service
  3. Card-Statement-Composite

They are the main focus and basically the business of our application, i.e. the microservices de facto. At the end of this, we are going to have a system similar to this picture.

microservices (1)

Hands on

Without further delay, let’s visit our well-known friend: http://start.spring.io and set-up a new project with these properties:

Screenshot from 2016-03-31 21:03:08

Generate a: Maven Project
Spring Boot: 1.3.3
Group: com.spring.netflix.oss.microservices
Artifact: card-service
Dependencies:
Actuator, Web, Config Client, Eureka Discovery

Generate project / Extract your file inside of your workspace directory / Import the project into your IDE (if you have questions about how to do that, see this steps in our previous tutorial).

Screenshot from 2016-03-31 20:50:10

First, edit the class CardServiceApplication because we need to add a desirable behaviour to it: @EnableEurekaClient that, as previously said, is in charge to say to Eureka that this project is one of his suitable clients to be automatically registered.

The final code:
package com.spring.netflix.oss.microservices;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class CardServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(CardServiceApplication.class, args);
    }
}

 

Now, another step that we’ve frequently done here: remove the file application.properties from src/main/resources and add a new file under the same path, called: bootstrap.yml.

Screenshot from 2016-03-31 21:06:51

The code for bootstrap.yml:

spring:
  application:
    name: card-service
  cloud:
    config:
       uri: http://localhost:9090

Next, the awaited moment, some real codes – but don’t be very excited because for this example, I wrote a very simplistic piece of code.

Create a package called: model under com.spring.netflix.oss.microservices.

Screenshot from 2016-03-31 21:14:15

Inside this package, create a class named Card:

package com.spring.netflix.oss.microservices.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown=true)
public class Card {
	private Long id;
	private String cardHolderName;
	private String pan;
	private String validDate;
	
	public Card() {
		super();
	}
	
	public Card(Long id, String cardHolderName, String pan, String validDate) {
		super();
		this.id = id;
		this.cardHolderName = cardHolderName;
		this.pan = pan;
		this.validDate = validDate;
	}



	public Card(String cardHolderName, String pan, String validDate) {
		super();
		this.cardHolderName = cardHolderName;
		this.pan = pan;
		this.validDate = validDate;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getCardHolderName() {
		return cardHolderName;
	}

	public void setCardHolderName(String cardHolderName) {
		this.cardHolderName = cardHolderName;
	}

	public String getPan() {
		return pan;
	}

	public void setPan(String pan) {
		this.pan = pan;
	}

	public String getValidDate() {
		return validDate;
	}

	public void setValidDate(String validDate) {
		this.validDate = validDate;
	}

	@Override
	public String toString() {
		return "Card [id=" + id + ", cardHolderName=" + cardHolderName + ", pan=" + pan + ", validDate=" + validDate
				+ "]";
	}

}


One more package, api, also under com.spring.netflix.oss.microservices.

Screenshot from 2016-03-31 21:09:35

Then create a new class named as CardServiceController. Here the code for this:

package com.spring.netflix.oss.microservices.api;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javax.annotation.PostConstruct;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.spring.netflix.oss.microservices.model.Card;

@RestController
@RequestMapping(value="/api")
public class CardServiceController {
	
	private List<Card> fakeRepo;
	
	@PostConstruct
	public void init(){
		this.fakeRepo = new ArrayList<>();
		fakeRepo.add(new Card(1l, "John Warner", String.valueOf(Math.random()).substring(0, 16),"11/20"));
		fakeRepo.add(new Card(2l, "Paul Crarte", String.valueOf(Math.random()).substring(0, 16),"09/25"));
		fakeRepo.add(new Card(3l, "Ana Hassent", String.valueOf(Math.random()).substring(0, 16),"01/19"));
		fakeRepo.add(new Card(4l, "Elena Tarin", String.valueOf(Math.random()).substring(0, 16),"06/22"));
		fakeRepo.add(new Card(5l, "Wending Qua", String.valueOf(Math.random()).substring(0, 16),"03/25"));
		fakeRepo.add(new Card(6l, "Julio Sanch", String.valueOf(Math.random()).substring(0, 16),"09/18"));
		fakeRepo.add(new Card(7l, "Adolf Bianc", String.valueOf(Math.random()).substring(0, 16),"07/22"));
		
	}
	
	@RequestMapping(value="/cards", method = RequestMethod.GET)
	public List<Card> getCards() {
		return fakeRepo;
	}
	
	@RequestMapping(value="/card/{cardId}", method = RequestMethod.GET)
	public Card getCard(@PathVariable Long cardId) {
		return Optional.ofNullable(
				fakeRepo
				.stream()
				.filter((card) -> card.getId().equals(cardId))
                .reduce(null, (u, v) -> {
                    if (u != null && v != null)
                        throw new IllegalStateException("More than one CardId found");
                    else return u == null ? v : u;
                })).get();
		
	}

	@RequestMapping(value = "/new-card", method = RequestMethod.POST, headers = "Accept=application/json")
	public void createCard(@RequestBody Card newCard) {
		if(newCard.getId()!=null){
			fakeRepo.add(newCard);
		}
		System.out.println("New card passing: " + newCard);
	}
}

We are almost there. Navigate until our config folder path, i.e. ~/dev/workspace/spring-netflix-oss-microservices/microservices-config/MASTER and create a new file called card-service.yml. Follows the image and the code:

Screenshot from 2016-03-31 21:51:01

server:
port: 8904

eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/

 

Again: it’s important to pay attention in the order that some tasks are done. Remember that in our previous post (Edge-Server), it was necessary to commit and push our code from configuration to github before trying to Run/Debug the application. In this section, we must do the same:

$cd ~/dev/workspace/spring-netflix-oss-microservices/microservices-config
$git add .
$git commit -m "Configuration for card-service"
$git push origin master

... * Provide your credentials and the push will work * ...

Once it’s done, we can return to the IDE and start our services in the respective order:

1st – Config-Server
2nd – Discovery-Service

Then Edge-Server, Card-Service (no matter the order here). By the end, the result is going to be:

Screenshot from 2016-03-31 22:09:44

Now that we have a really business code and that we’ve just exposed an API, we can start to “consume” our fictitious API just to test it.

You can access, for instance – http://localhost:8904/api/cards, the expected result is:

Screenshot from 2016-04-02 17:52:34

One more: http://localhost:8904/api/card/3

Screenshot from 2016-04-02 17:54:30

Ok, that is all for today.

Soon, we will continue our serieโ€ฆ

Thanks.

Edge Server – Netflix Zuul

Before we start

If you hit this page without following the Step-by-step into Micro-Services Architecture with Spring and Netflix OSS, it can be useful to know about the serie:

Part 3.

Frequently (to not say every time) that we build a system, we need to expose some kind of integration with the external world. By external world, I mean:

  • people accessing through browser, mobile apps, etc;
  • dependency between services – i.e.: a system that consumes another;
  • interactions between a legacy system and a pretty new one or, for instance, integrations between systems built in different programming languages.

By these simple examples, we can imagine sorts of another possibilities. Grounded by these possibilities, it is comfortable to say that in most cases, we will depend of an exposure of API to this “external world” to interact.

With this we can leverage easily some concerns: to guarantee that only authorized people / roles / systems will invoke upon our service layers; be aware that the minimum exposure points of our system are available, i.e. it would be an asset to have just one bridge / proxy to control.

Given this, emerges the Netflix Zuul. I’ll let the Netflix team explain by themselves (after all, they have more property to talk about their creation) ๐Ÿ™‚

What is Zuul?

Zuul is the front door for all requests from devices and web sites to the backend of the Netflix streaming application. As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security. It also has the ability to route requests to multiple Amazon Auto Scaling Groups as appropriate.

Why did we build Zuul?

The volume and diversity of Netflix API traffic sometimes results in production issues arising quickly and without warning. We need a system that allows us to rapidly change behavior in order to react to these situations.

Zuul uses a range of different types of filters that enables us to quickly and nimbly apply functionality to our edge service. These filters help us perform the following functions:

  • Authentication and Security – identifying authentication requirements for each resource and rejecting requests that do not satisfy them.
  • Insights and Monitoring – tracking meaningful data and statistics at the edge in order to give us an accurate view of production.
  • Dynamic Routing – dynamically routing requests to different backend clusters as needed.
  • Stress Testing – gradually increasing the traffic to a cluster in order to gauge performance.
  • Load Shedding – allocating capacity for each type of request and dropping requests that go over the limit.
  • Static Response handling – building some responses directly at the edge instead of forwarding them to an internal cluster
  • Multiregion Resiliency – routing requests across AWS regions in order to diversify our ELB usage and move our edge closer to our members

Hands on

So far, in our system landscape we’ve just created a Config-Server and a Discovery server. Now, this part is easy and pretty small than the previous one.

To start, visit http://start.spring.io and we’ll set-up our project.

Generate a: Maven Project
Spring Boot: 1.3.3
Group: com.spring.netflix.oss.microservices
Artifact: edge-server
Dependencies:
Actuator, Zuul, Config Client, Eureka Discovery

Screenshot from 2016-03-21 22:55:34

Generate project / Extract your file inside of your workspace directory / Import the project into your IDE (if you have questions about how to do that, see this steps in our previous tutorial).

First of all, edit the class EdgeServerApplication because we need to add two desirable behaviours to it: @EnableEurekaClient and @EnableZuulServer the annotations talk by themselves, however, to clarify, the first one is in charge to say to Eureka that this project is one of his suitable clients to be automatically registered. The second one tells to Spring that this client will act as a Zuul Server (our Gatekeeper – By the way, I am not that geek-nerd guy that know all about geek movies. I felt stupid when I discovered that Zuul was a name related to Ghostbuster movies ๐Ÿ˜ – shame on me).

Ok, sorry for suddenly changing the subject, let’s see the code:

package com.spring.netflix.oss.microservices;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulServer;

@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulServer
public class EdgeServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EdgeServerApplication.class, args);
    }
}

Now, we will remove the file application.properties from src/main/resources and add a new file under the same path, called: bootstrap.yml. The purpose here is to define a name for our module and setup the location of our config server (from our previous post).

spring:
    application:
        name: edge-server
    cloud:
        config:
            uri: http://localhost:9090

Finally, navigate until our config folder path, i.e. ~/dev/worspace/spring-netflix-oss-microservices/microservices-config/MASTER and create a new file called edge-server.yml. It will have some basic configurations about how the self registration service will find this new module and the port that the service is going to run. Follows the code:

server:
    port: 8765

eureka:
    client:
        serviceUrl:
             defaultZone: http://localhost:8761/eureka/

Simple, don’t you agree? With this we have our Zuul pratically ready and when we move on in the blog serie, you will understand this purpose. By now, we will run the set of applications to see if everything is ok.

It’s important to pay attention in the order that some tasks are done. For example, it is always necessary to commit and push your code from configuration to github before trying to Run/Debug the application. It is needed because our config-server is looking for its attributes externally.

$cd ~/dev/workspace/spring-netflix-oss-microservices/microservices-config
$git add .
$git commit -m "Configuration for edge-server"
$git push origin master

... * Provide your credentials and the push will work * ...

Once it’s done, we can return to the IDE and start our services in the respective order:

Config-Server
Discovery-Service
Edge-Server

Screenshot from 2016-03-25 12:35:00

Each one with its one responsability, they follow an important principle of software architecture – do only one thing and do it well. You can realize that they are completely decoupled and the code present in each one do not add dependencies from the other.

See you soon.

Config-Server & Discovery Service

Part 2.

 

If you hit this page without following the Step-by-step into Micro-Services Architecture with Spring and Netflix OSS, I strongly recommend you to read the following links:

What is a Config-Server?

Before dig into the micro-services in a literacy way (let’s say: the core of our application, that will keep our business rules) we need a centralized and straightforward manner to configure and retrieve the configurations about all the services that we’re supposing to develop. It’s also important because when we do this kind of “abstraction”, I mean – a centralized way to rule all configs, we are not carrying the burden of remembering where each configuration are distributed across multiple and distributed components.

Another advantage of keeping these configurations apart is, according to the official Spring’s web site (http://cloud.spring.io/spring-cloud-config/):

As an application moves through the deployment pipeline from dev to test and into production you can manage the configuration between those environments and be certain that applications have everything they need to run when they migrate.

So far, we are ย talking about an external way to manage this configuration, but, for those who are thinking “where could be a good place to keep this important files?”, for this step-by-step I’ll suggest git (if you are not familiar with git, it’s a good time to start learning – trust me, soon or later you will need it).

git

 

Hands-on

First of all, we must initiate an empty repository that will keep our code organised.

Properly logged on Github.com, just access:

https://github.com/new

Fill the available options in this way:

ย Repository Name: spring-netflix-oss-microservices

Description: Our microservice architecture parent project

Check the Public option

Initialize this repository with a README

And click -> Create a Repository button

Screenshot from 2016-03-20 09:11:37

Once you create, you will see a Github page like this:

Screenshot from 2016-03-20 09:14:53

Copy the URL from HTTPS text box, go until your favourite cmd, navigate until your workspace path and do a clone of this project. Example:

fernando@fernando-Vostro-5470:~$ cd ~/dev/workspace/
fernando@fernando-Vostro-5470:~/dev/workspace/$ git clone https://github.com/fernandoabcampos/spring-netflix-oss-microservices.git
Cloning into 'spring-netflix-oss-microservices'...
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
Checking connectivity... done.

Attention for this command:

git clone https://github.com/fernandoabcampos/spring-netflix-oss-microservices.git
Obviously with the https url that you copied from your github.

It does the “magic” for us.

For now, leave this project empty and soon we’ll use it again.

Given this very beginner introduction, let’s start the good part – work with Spring. There are some ways to create a Spring Boot application. We’ll create through the easiest one (website), but let’s show another for the command line guys ๐Ÿ˜‰

It is pretty simple, on you command line just type:

curl start.spring.io

It’s possible that you don’t have CURL installed on your machine – follow the instructions according to your O.S. to have it installed whether you want do in the command line way.

The result that you’ll see is, in short, something like this:

$ curl start.spring.io


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 
:: Spring Initializr ::  https://start.spring.io
...

By the end there are some explanations about how to create each kind of project – if you curious about, you can see the full return of this curl command here.

Return to what I consider the easiest way to create a Spring Boot project, access:

http://start.spring.io/

For this example, although particularly Iย have a thing for Gradle, let’s select:

  • Generate a: Maven Project
  • Spring Boot: 1.3.2
  • Project Metadata:
    • Group: com.spring-netflix-oss.microservices
    • Artifact: config-server
  • Dependencies
    • Config Server
    • Actuator

By the end, your set-up will be like this:

Screenshot from 2016-02-24 22:39:39

As soon as you click at “Generate Project” the download will start automatically and a zip file with the name config-server.zip will be delivered to you.

Unzip it into your project path – for whom those are not familiar with this, I like to keep my projects underย ~/dev/workspace, so the pwd of our unzip would be ~/dev/workspace/spring-netflix-oss-microservices/config-server.

Info:ย  It’s a particular decision, but it’s recommended to do so – the following modules will play easily if we keep our code organised.

 

Inside your IDE

File / Import …

Screenshot from 2016-03-17 21:26:23

Choose: Existing Maven Project

As the option Select Root Directory: ~/dev/workspace/spring-netflix-oss-microservices/config-server
Project: pom.xml from our config-server

Screenshot from 2016-03-16 22:33:17

Finish.

Our project will be imported into our IDE and we are now ready to start.

We’ll create an application.yml file that mainly is responsible for dictating some important points, for instance, the server port that this server will run and also for where our server will look up when finding configs.

To do so, under Package Explorer, select the src/main/resources folder, right click, New -> File.

Now create a file named as: application.yml

Screenshot from 2016-03-20 08:52:16.png

We’ll fill this file later.

At the same place, there is another file called application.properties, you can select and delete it because we won’t use (once that application.yml do the same for us).

Screenshot from 2016-03-16 22:41:31

Lastly, at the same path, create a bootstrap.yml file that will allow us to determine a name of our module. The content of this file is just:

spring:
    application:
        name: config-server

It was aforementioned that we’ll use git for managing our config project, so, without further ado, let’s create another repository:

Properly logged on Github.com again, just access:

https://github.com/new

Set-up your new repository as follows:

Screenshot from 2016-03-16 22:47:24

And create your repo.

Once you finished, you will have something like this:

Screenshot from 2016-03-16 22:53:35

Copy the text box, labeled here as HTTPS, with the URL from your project that you just create. Go until your favourite cmd, navigate until your workspace / project path and do a clone of this project. Example:

fernando@fernando-Vostro-5470:~$ cd ~/dev/workspace/spring-netflix-oss-microservices/
fernando@fernando-Vostro-5470:~/dev/workspace/spring-netflix-oss-microservices$ git clone https://github.com/fernandoabcampos/microservices-config.git
Cloning into 'microservices-config'...
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
Checking connectivity... done.

 

Attention for this command:

git clone https://github.com/fernandoabcampos/microservices-config.git
Obviously with the https url that you copied from your github.


As the tutorial moves on, you will realize for what this project was created. By now, that is all we need.

Returning to the Config-Server, we need to say to Spring that this project is a Config Server. We do this by adding @EnableConfigServer in our main class, i.e. ConfigServerApplication under

src/main/java/com.spring.netflix.oss.microservices.ConfigServerApplication

See the code:

package com.spring.netflix.oss.microservices;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigServerApplication.class, args);
	}
}

 

One more stuff to do is to edit the application.yml that we created some steps ago. There we’ll add some important informations about the location of our config-server. Edit it and add (don’t forget to substitute the uri for your own repository):

# Defines the port where the config server is running so that rest of the services can pick up
# their external configurations
server:
    port: 9090 

spring:
    cloud:
        config:
            server:
                git:
                    uri: https://github.com/fernandoabcampos/microservices-config.git
                    searchPaths: MASTER

 

With this simple configuration we are saying to Spring that we want to run at 9090 Port, and the rest of the configuration will be found at our GitHub repo. Note that we defined a specific searchPaths. It is what we are going to create now. It is easy -> inside your microservice-config folder, just create an empty folder called MASTER. Latter will push all of this to Github and the configuration above will be Ok.

Screenshot from 2016-03-20 10:57:57

 

Wow, take a deep breath.

Discovery Service

Well, we did a scaffold of our config-server – there is some steps over it that appear in some minutes. Nevertheless, if we want to build a really distributed microservices architecture, we will need to have a mechanism that allow us to register new instances of our services automatically (be them support services or core services), i.e., once the microservice is up, this mechanism will help through a self-register and keep a tracking of the ports, for example.
It is substantial because we need to build a scalable, resilient and fault-tolerant system. Without this mechanism, we would have to maintain a list of ports, servers and be aware of all systems ongoing.

For this purpose, we choose the Netflix Eureka. Suggestive name, no?

What is Eureka? (according to its own documentation)

Eureka is a REST (Representational State Transfer) based service that is primarily used in the AWS cloud for locating services for the purpose of load balancing and failover of middle-tier servers. We call this service, the Eureka Server. Eureka also comes with a Java-based client component,the Eureka Client, which makes interactions with the service much easier. The client also has a built-in load balancer that does basic round-robin load balancing. At Netflix, a much more sophisticated load balancer wraps Eureka to provide weighted load balancing based on several factors like traffic, resource usage, error conditions etc to provide superior resiliency.

Given this, we know that we’ll have two kind of Eureka Components – the Eureka Server and the Eureka Clients. Let’s do the first of them:

Screenshot from 2016-03-20 11:45:43

The procedure is the same than other services that we already build.
Visit http://start.spring.io, create your project as the image above and import into IDE.

Without wasting our time, edit the class DiscoveryServiceApplication and add @EnableEurekaServer.

package com.spring.netflix.oss.microservices;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class DiscoveryServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(DiscoveryServiceApplication.class, args);
    }
}

 

After this, in src/main/resources, delete application.properties that must be present there and create a new File called bootstrap.yml. The purpose of this file is to define a name for this sub-project and to set-up the configuration server for which the application will look at.

Created the file, add the following info inside it:

spring:
    application:
        name: discovery-service
    cloud:
        config:
            uri: http://localhost:9090

Easy peasy! Note that we are pointing to 9090 port. It isn’t random – we sure are point to configuration-server that we just created steps ago.

Almost done… The next step is to create a file called discovery-service.yml under:

/dev/workspace/spring-netflix-oss-microservices/microservices-config/MASTER

The content of this file is:

server:
    port: 8761

# Defines the Eureka server that is used by the Netflix OSS components to use as the registry
# for server discovery
eureka:
    instance:
        hostname: localhost
        leaseRenewalIntervalInSeconds: 5
    client:
        registerWithEureka: false
        fetchRegistry: false
        serviceUrl:
            defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

 

The configuration is ready, do a push for your remote repository (otherwise when we try to start our config-server, it will not find the appropriate PATH: MASTER that we just put.

fernando@fernando-Vostro-5470:~$ cd /dev/workspace/spring-netflix-oss-microservices/microservices-config/
fernando@fernando-Vostro-5470:~/dev/workspace/spring-netflix-oss-microservices$ git push origin master
...

 

Ok, the files are remote and up-to-date now.

Finally, we can run our application. On Boot Dashboard panel, select the config-server and run. Later, do the same with discovery-service.

Screenshot from 2016-03-20 12:29:39

Well, too much for while.

The next step is to build a gatekeeper (Zuul Proxy); fault tolerance logic (hystrix); monitor dashboards, the core services themselves.

I hope this tutorial can be useful for your.

 

See you soon with the next part.

Microservice Architecture – Step by Step Tutorial

Part 1.

  • Before we start
  • Inspirations and Goals
  • Scenario – application scope
  • Tool suite (Spring cloud, Netflix OSS)
  • Another links

 

Before we start

It would be a good starting point to know something about who I am:

Inspirations and Goals

The term “MicroService Architecture” is neither new nor secret to anyone that develops software. As stated by Martin Fowler:

The term “Microservice Architecture” has sprung up over the last few years to describe a particular way of designing software applications as suites of independently deployable services. While there is no precise definition of this architectural style, there are certain common characteristics around organization around business capability, automated deployment, intelligence in the endpoints, and decentralized control of languages and data.

However, although we have a lot of theory involved in this architecture, I really believe that we don’t have so many tutorials (step by step) explaining how to start a project with this structure from scratch.

Some weeks ago I’ve come across with this excellent Blog Series – Building Microservices written by Magnus Larsson. As he described very well about all the concepts and also provided the code, I decided to do the example by own my own, adapting it as my needed for a real project and now I can take this code as my blog post, where the purpose of this small article / tutorial is to clarify and help people who never have created an application based on microservice architecture to start from scratch and understanding a little bit more about this trend.

If you arrived here looking for an ultra expert in Spring / Microservice Architecture / Netflix OSS or something like this, probably this page will not fit what you are looking for ๐Ÿ™‚

Scenario – application scope

Our fictitious scenario is a financial application from credit cards. The core of our application (where the real business logics live) is composed by 3 microservices that communicates among them.

Essentially:

  1. Card-Service
  2. Statements-Service
  3. Card-Statements-Composite
When the blog posts move on, we’ll get there. Be patient ๐Ÿ˜›

But beside that, we need a set of support services that are designed each one for a bounded purpose – for instance – edge server, dynamic routing, discovery service, among others. We’ll discuss each one as soon as they arrive in our system, however, for the anxious, Magnus have already gave us a portrait of them right here [item 4].

Tool suite (Spring cloud, Netflix OSS)

For this tutorial, I’ll assume that you have an environment with this requirements:

  • Java 8
  • Maven
  • Git
  • Your preferred IDE (I’d suggest Spring Tools Studio, but feel free to use another you want).

The main components that we will create are based on Spring and Netflix OSS projects.

 

Another Links

Here you can follow the whole serie:

Part 2: Config-Server and Service Discovery

Part 3: Edge Server

Part 4.1: Core Business Development โ€“ Cardย Service

Part 4.2 and 4.3 Core Business โ€“ Statement Service and CardStatementComposite

Part 5 – Hystrix / Monitor Dashboard and Turbine

More for coming …

As soon as I have new contents, I’ll include here the links.