# Micronaut  - Discovery Client and Client-side load balancing with Consul

### Introduction 
In any microservice architecture, we need multiple instances of the services. Our superhero API is no different. While we have been running only one instance of superhero API and command center, it is far from reality.

 In the real world, the load on servers is expected to increase. We need to establish efficient communication to talk between services. 

Suppose, there is a surge in load,  we need to increase the instances of superhero API, how will the command-center know the new instances URLs. How will it call them and balance the load on servers? Till now, we hardcoded it with the ```@Client``` annotation and value as URL. 

Can we solve this problem if we have another service that can keep track of all the services deployed? If it can know all the instances of any service and can give us the URLs. How good it could be if we distribute the load among all available instances. 

In this section we will solve this using Consul Service discovery and client-side load balancing. 


### Approach
- #### Add the discovery dependency to command-center and superhero api.
- #### Run consul
- #### Update the ```@Client``` annotation to use ```id``` of the service rather URLs

####  Add the discovery dependency to command-center and superhero api.
When we add this dependency and let client know that they have to register at consul service discovery, client will sent HTTP request at startup. it keeps sending the request at regular interval to let the consul service discovery app know that its up and running.

![superhero API.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1632763989300/1F3qLg-y2.png)

Add the below dependency to the superhero API and command center poms

```
  <dependency>
            <groupId>io.micronaut.discovery</groupId>
            <artifactId>micronaut-discovery-client</artifactId>
            <scope>compile</scope>
        </dependency>
```
Once it is added, we will tell apps the address of the consul server so that they can register themselves. 

Add the below in superhero and command-center application.yml
```
consul:
  client:
    registration:
      enabled: true
    defaultZone: "${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}"
```

This will tell the application about the address of the consul server. At the start of microservices, they will hit the server on this port to let it know about their availability.


 #### Run consul

There are many ways to run consul, let us keep simple with docker, run below docker command to run it

```
docker run -p 8500:8500 consul
```
This will sun consul app and expose to 8500 port. 

#### Update the ```@Client``` annotation to use ```id``` of the service rather URLs
Till now we have used hardcoded ```@Client``` value , let us use id rather than URL now. Ids are the same as Micronaut's  application name . 
We will update the declarative client used in the last section with id.

Below is the code 
```

@Client(id = "superHeroes")
@Header(name = "Accept", value = HEADER_ACCEPT)
public interface SuperheroClient {
    @Get("/rx/superheroes")
    Flux<Superhero> superheroes();

    @Get("/rx/superhero/{id}")
    Mono<Superhero> superheroesById(Long id);

    @Post("/rx/superhero")
    Publisher<Superhero> create( @Body  Superhero superhero);

    @Put("/rx/superhero")
    Publisher<Superhero> update( Superhero superhero);

    @Delete("/rx/superhero/{id}")
    Publisher<HttpResponse<Long>> delete(Long id);
}


``` 
If you observe we have updated ```@Client``` with id of superhero API.  Whenever a call to superhero API is made, it can select one of the instances that have registered itself at consul. 

#### Test The Setup 
Once it is all done , it's time to test the setup. To do that let us start multiple instance on superhero API. We can start them by directly invoking jar in the ```target``` folder and passing ```micronaut.server.port={PORT_NO}``` as parameter. 

Open two terminals and navingate to project. Change directory to target folder and run the command
```
 java -jar .\super-heroes-0.1.jar --micronaut.server.port=8082

```

```
 java -jar .\super-heroes-0.1.jar --micronaut.server.port=8081

```

The above commands will start two instances of superhero API at 8081 and 8082 port. You will notice the application will register itself with consul and log it.


#### Superhero API Registered at consul at port 8081

![RegisterATConsul0.PNG](https://cdn.hashnode.com/res/hashnode/image/upload/v1632786784055/ctcALHOUp.png)


#### Superhero API Registered at consul at port 8082


![RegisterATConsul1.PNG](https://cdn.hashnode.com/res/hashnode/image/upload/v1632786865515/JG9ltVPXy.png)


#### Start command-center App and Test the sever

Once command-center all is up and you can see it registered to consul, you can verify all of them are at consul UI too. visit ```http://localhost:8500``` where docker is running the consul 


![consulAppunnig.PNG](https://cdn.hashnode.com/res/hashnode/image/upload/v1632787241444/fnWHIlcHB.png)

If you hit the API via command-center, You can see logs are different console widows of superhero API.

This shows the working load balancing of HttpClient with consul.









 



