Sunday, March 24, 2019

Microservices - Service Discovery

Greeting!

In a monolithic architecture we have all our business logic in one place. We can directly use relevant service through the respective component.
When it comes to microservices our business logic is in multiple places working independently. This introduces new problems.

  • How does a service find another service? (hard code url hah?)
  • How do we monitor health conditions?
  • Maintaining address, port
  • How to load balance for dynamic IPs.
How about another microservice to handle all these problems?

Service Registry And Discovery Pattern

Service registry is like your address book. It has all the address' you need. When you need to find a place, you get the address book to locate it. Service registry is doing exactly the same thing. It maintains other microservices names, addresses, ports, health.
Other microservices register themselves with the registry with necessary information. Discovery service relying on the heartbeat for services availability. Eureka service expects 3 heartbeats in 10sec for each. Once it is registered, other microservices can use name of the another microservice to call it. 


Implementing with Eureka

Eureka service discovery is the Netflix's solution for the service registration and discovery. It is well battle tested and easy to use library with Spring boot.
Netflix Eureka gives both server and client.

These are the steps needed;

  1. Go to start.spring.io
  2. Add Eureka Server, Actuator
  3. Enable Eureka server adding @EnableEurekaServer 
  4. Configure the server modifying application.yml
  5. Test it http://localhost:8761/

Maven dependencies

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Bootstrap class

@EnableEurekaServer
@SpringBootApplication
public class DiscoveryServerApplication {

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

}

discovery-service.yml

eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}

Commit configuration file to configuration server. Run the application and go to http://localhost:8030/ in your browser.

Eureka Client

  1. Go to start.spring.io
  2. Add Web, Eureka Discovery, Actuator
  3. Enable Eureka client adding @EnableEurekaClient
  4. Configure the client modifying application.yml
  5. Test it http://localhost:8761/

Maven dependency

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

Enable Eureka client

@EnableEurekaClient
@EnableFeignClients
@SpringBootApplication
public class ShoppingCartServiceApplication {

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

}

Update configuration file(s)

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

When the microservices are starting you can see something like this in console.
Registering application CATALOG-SERVICE with eureka with status UP

When you go to Eureka server it will be like this. (I have started two catalog-service instances)


Ribbon with Eureka

With Netflix and Spring, these things are very easy. Just remove the configuration we added earlier. Ribbon uses service name to fetch URLs from Eureka and cache it. Even if the Eureka is down, Ribbon uses it's cached URLs.
#catalog-service:
#  ribbon:
#    listOfServers: localhost:8010,localhost:8011

Test it

Use this cURL or get the postman collection to invoke bill end point. Observe the console outputs. You will see logs in both catalog service instances.
curl -X POST \
  http://localhost:8020/bill \
  -H 'Content-Type: application/json' \
  -d '{
    "cartItems": [
        {
            "productId": "01",
            "quantity": 2
        },
        {
            "productId": "03",
            "quantity": 1
        }
    ]
}'




No comments:

Post a Comment