Service Registration and Service Discovery


I consider there is no better way to understand why/what/how Service Discovery and Registration can do, if you don't see this video of Ruslan Meshenberg from Netflix

Also you can see a quick introduction in Spring here and here.

And a little bit of Archimedes :-)


Basically, in this repository you can find this simple architecture:

So, we have 3 Microservices:
* 1 Spring Boot Server. * 1 Spring Boot Client to be discovered. * 1 Spring Boot Client to discover and use the previous client.

Let's see how simple it is to configure the 3 of them:

Server Configuration

You need to specify in the AppBoot the following annotation: @EnableEurekaServer
Inside the application.yml you need to declare the following parameters:

  port: 8761 --> to run this example locally, we need to use different ports. 

    hostname: localhost --> for localhost test.
    registerWithEureka: false --> this is the server, so we don't need to register itself
    fetchRegistry: false --> same as before. 
      defaultZone: ${EUREKA_URI:http://localhost:9000/eureka} --> get a zone URL
Clients Configurations

You need to specify in the AppBoot the following annotation: @EnableEurekaClient

    name: spring-cloud-eureka-client --> this is the "DNS" that will be registered in Eureka Server, so to reach this client, it will be: http://spring-cloud-eureka-client:8081

  port: 8081 --> different port to run this locally. 

    registerWithEureka: true --> enable register.
    fetchRegistry: true --> enable fetch.
    useDnsForFetchingServiceUrls: false --> not needed in this example.
    eurekaServerDNSName: localhost --> host
    eurekaServerPort: 8761 --> port where the server is running
    eurekaServerURLContext: eureka --> context for zone URL.

Bear in mind that these parameters can be configured and parametrised in different ways. This way is only to show a simple example in localhost.

Discover and Registration

Overall, we have 2 different ways to discover a service:

  1. By Service Reference: In order to use the option, we need to add in Client1 pom.xml the Client2 reference and user the interface:
  // this is client2
    private EurekaClientApplication eurekaClientApplication; // this is Client1 service.

    public String greeting(Model model) {
        model.addAttribute("remote-client-response", eurekaClientApplication.eurekaClientRemoteExample());
        return "remote-client-response-view";

Personally I consider this option a bit messy, consider you have > 50 Microservices (MS), you need to configure every pom.xml for every MS and also manage the version between them (e.g. MS1 is version 1.0 that is using MS2 version 3.5 and MS3 version 4.5).

  1. By RestTemplate:
    RestTemplate restTemplate;

    public String getGreetingWithRestTemplate(Model model){
            Application application = eurekaClient.getApplication("spring-cloud-eureka-client"); --> this is the "DNS" we registered. 

            InstanceInfo instance = application.getInstances().get(0); --> we obtain the instance.
            URI uri = UriComponentsBuilder.fromUriString(instance.getAppName()).build().toUri(); --> build the URI dynamically. 
            String response = restTemplate.getForObject("http://" + instance.getHostName() +":" + instance.getPort()+"/restTemplateRemoteMethodExample", String.class); --> get the response back from the client2. 
            model.addAttribute("remote-client-response", response);

In this option, we can segregate versions and implementations and we follow one of the principles of MS: single (and simple) responsibility.