Spring cloud, Eureka, Ribbon, Feign example


Goal of this example

This example explains one of the most important microservice pattern, the service registry. As a related topic we will cover the topics of client side load balancing and declarative rest clients.

Technology Used

  • Spring boot 1.3.5.RELEASE
  • Eureka
  • Ribbon
  • Feign

Why do we need service registry?

  • A microservice ecosystem may consist of a high number of services that need to know each other’s location. If we have multiple environments (dev, qa, uat, prod) then configuring all these services can be very time consuming and error prone.
  • in a cloud environment the ip address and port of the services are not known in advance. Based on demand new service instances can be added or removed on the fly.

The solution is to create the “telephone book” of services, called service registry. Spring cloud is integrated with Eureka from Netflix OSS, Consul and Zookeeper

Starting up an Eureka server

Eureka was created and opensourced by Netflix. Spring created a nice wrapper around it, so it can be started up as a spring boot application. It is as easy as downloading an empty spring boot skeleton and adding the following dependency

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>

then annotating the main class like this :

 
@SpringBootApplication 
@EnableEurekaServer 
public class Application 

If we start up the application and open it e.g.: http://localhost:8761/ then we will see the admin screen of Spring-cloud Eureka. At this point there are now services registered.

Registering a service into Eureka

To make an application register itself to eureka we need to add the following dependency

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>

add the @EnableEurekaClient annotation to our spring boot main class

@EnableEurekaClient
public class Application

and add some configuration to application.yml or application.properties

eureka:
  instance:
    leaseRenewalIntervalInSeconds: 1
    leaseExpirationDurationInSeconds: 2
  client:
    serviceUrl:
      defaultZone: http://127.0.0.1:8761/eureka/
    healthcheck:
      enabled: true
    lease:
      duration: 5

spring:
  application:
    name: customer-service

There are two important settings here :

  • eureka.client.serviceUrl.defaultZone : The url of the eureka server. This is the only well known ip address.
  • spring.application.name : Our service will be registered by this key. Other services can reference it by this.

Once we start up our service then go back to the eureka console we will see that “customer-service” is registered.

Client side load balancer and service discovery : Ribbon + RestTemplate

Client can query service location by application name. Eureka client is integrated with RestTemplate, all we need to do is register a RestTemplate as a bean and annotate with @LoadBalanced

@Configuration
public class Config {

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

then use the rest template. Instead of addressing the service by URL we can reference services by name, e.g.: http://customer-service/customer/

 
@Autowired 
private RestTemplate restTemplate; 

public MessageWrapper<Customer> getCustomer(int id) { 
    Customer customer = restTemplate.exchange( "http://customer-service/customer/{id}", HttpMethod.GET, null, new ParameterizedTypeReference<Customer>() { }, id).getBody(); 
    return new MessageWrapper<>(customer, "server called using eureka with rest template"); 
} 

Auto generated rest client with client side load balancer and service discovery : feign

REST interfaces can be very effectively used “natively” from javascript and node js, but languages with compile time time type check, require a client library. Java developers spend a lot of time writing write boilerplate code for REST clients. Feign offers a solution to dynamically generate clients from the interface. Additional benefit is that we can keep the signature of the service and client identical. First we need to declare an interface with all the Spring request mapping annotations :

public interface CustomerService {

    @RequestMapping(value = "/customer/{id}", method = RequestMethod.GET, produces = "application/json")
    Customer getCustomer(@PathVariable("id") int id);
}

then we can create an another interface extending it :

@FeignClient(value = "customer-service")
public interface CustomerServiceFeignClient extends CustomerService {
}

the value parameter will contain the service name to be looked up from Eureka. If Eureka is not used then URL can be specified as well

@FeignClient(url = "http://example.com")
public interface CustomerServiceFeignClient extends CustomerService {
}

Then we can declare our controller like this

@RestController
public class CustomerController implements CustomerService {

The client can be used like this

class CustomerFeignController {

    @Autowired
    private CustomerServiceFeignClient customerServiceFeignClient;

Spring dynamically generates an implementation of the feign client and instantiate it as a spring bean, if we add the following configuration

@EnableFeignClients(basePackageClasses = CustomerServiceFeignClient.class)
@ComponentScan(basePackageClasses = CustomerServiceFeignClient.class)
public class Application {

Feign clients can also implement custom error handling, by specifying the fallback

@FeignClient(value = "customer-service", fallback = CustomerServiceFeignClientFallback.class)
public interface CustomerServiceFeignClient extends CustomerService {
}

One comment

  1. Thank you! That helped a lot.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: