Show List

Service Discovery Demo - Using Eureka Service Discovery

When there are multiple instances of the microservices, service helps to maintain the information (IP address and port) of the instances and providing the connection to the client and providing load balancing.

In our example lets say the "order" service needs to call the "payment" service while processing the order. If we did not have service discovery, order service would be calling the payment service using it's IP address and port.

OrderApplication.java
Add a bean for rest template. It will be used in the controller to call the post method of "payment" service.
package com.springcloud.servicediscovery.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableEurekaClient
@SpringBootApplication
public class OrderApplication {

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

@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
OrderController.java:
package com.springcloud.servicediscovery.order.controller;

import com.springcloud.servicediscovery.order.dao.OrderRepo;
import com.springcloud.servicediscovery.order.model.Order;
import com.springcloud.servicediscovery.paymnt.model.Payment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;


@RestController
public class OrderController {
@Autowired
private OrderRepo repo;

@Autowired
private RestTemplate restTemplate;

@GetMapping("/orders")
private List<Order> getAllStudents(){
return (List<Order>) repo.findAll();
}

@PostMapping("/orders")
private Order addOrder(@RequestBody Order newOrder){
Order ordResp = repo.save(newOrder);

Payment pmt = new Payment();
pmt.setOrderId(ordResp.getOrderId());
pmt.setPaymentAmt(ordResp.getPrice() * ordResp.getQuantity());

Payment pmResp = restTemplate.postForObject("http://localhost:9002/payments", pmt, Payment.class);
return repo.save(newOrder);
}
}
As we see, here we have to keep track of host name (or ip address) and port of the payment service. Which will because challenging specially when there are multiple instances of the service.

Using Service Discovery

In the application.yml file of the "payment" service, we had specified the name as "payment". So the service gets registered with this name in the Eureka server. So instead of using localhost:9002 to call the payment service through Rest Template, we can use "payment". Rest Template bean also needs to be annotated with @LoadBalanced annotation.

OrderApplication.java
package com.springcloud.servicediscovery.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableEurekaClient
@SpringBootApplication
public class OrderApplication {

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

@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
OrderController.java
package com.springcloud.servicediscovery.order.controller;

import com.springcloud.servicediscovery.order.dao.OrderRepo;
import com.springcloud.servicediscovery.order.model.Order;
import com.springcloud.servicediscovery.paymnt.model.Payment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;


@RestController
public class OrderController {
@Autowired
private OrderRepo repo;

@Autowired
private RestTemplate restTemplate;

@GetMapping("/orders")
private List<Order> getAllStudents(){
return (List<Order>) repo.findAll();
}

@PostMapping("/orders")
private Order addOrder(@RequestBody Order newOrder){
Order ordResp = repo.save(newOrder);

Payment pmt = new Payment();
pmt.setOrderId(ordResp.getOrderId());
pmt.setPaymentAmt(ordResp.getPrice() * ordResp.getQuantity());

Payment pmResp = restTemplate.postForObject("http://payment/payments", pmt, Payment.class);
//Payment pmResp = restTemplate.postForObject("http://localhost:9002/payments", pmt, Payment.class);
return repo.save(newOrder);
}
}
A post call to "orders" service should also call a post to "payment" service.
Source Code:

https://github.com/it-code-lab/spring-cloud-servicediscovery

    Leave a Comment


  • captcha text