Eureka Service Discovery – Consuming Services

In the previous article, we learned how to create a eureka server and how to register the client services to the service registry.

Before starting, go through the previous article to understand how to register a service into the eureka server.

In this article, we will learn different ways of looking up the registered services from the eureka server registry.

Using Eureka Client for service discovery

We will create two services with the service name my-client and my-client-2. We will consume the endpoint /call-me located in the first service from the second service, using service discovery.

With this approach, we will have a Eureka Client instance. We will use this instance to get the available instance from the eureka service registry. Then we call the call-me endpoint with the help of the rest template instance.

Create a eureka client application by adding the spring-cloud-starter-netflix-eureka-client dependency. Also, add the spring boot web dependency to the application.

With the STS IDE, we can choose the dependencies easily as shown below.

eureka service discovery

Update the spring boot application class file with the code given below.

We have added the @EnableEurekaClient annotation to register the service with the Eureka server for service discovery.

We have also created an HTTP GET API to expose the /call-me endpoint.

@SpringBootApplication
@EnableEurekaClient
@RestController
public class SpringBootEurekaClientApplication {
	@GetMapping("/call-me")
	public String method() {
		return "You are calling me through service discovery!!";
	}
	
	public static void main(String[] args) {
		SpringApplication.run(SpringBootEurekaClientApplication.class, args);
	}
}

Add the below property to the application’s property file. This property registers this service with the name my-client into the eureka server.

spring.application.name=my-client

Run the eureka client service with different port numbers. We can use runtime VM arguments to pass the server port numbers while starting the application.

With STS, we can right-click on project > Run As > Run Configurations > and set the VM argument as shown below.

running spring boot application on different ports

Now, we can access the Eureka server dashboard. We should be able to observe registered instances of the my-client service on the dashboard.

In the below image we have three instances of the service registered with port numbers 8080, 8081, and 8082.

registered clients on eureka server

Create the service consumer

Now create another similar eureka client service. This service will consume the my-client service.

Also, add the below properties into the application’s property file of the newly created service.

server.port=8090
spring.application.name=my-client-2

This service will run on the 8090 port and also register itself with the application name my-client-2.

Update the spring boot application class with the below code.

The @EnableEurekaClient annotation registers this service into the eureka server for service discovery. This is not a necessary step though in our example, as we are using this service to only consume the my-client service.

We have created a Rest Template bean. Also, we have used this bean to invoke the my-client service’s /call-me endpoint.

We have added REST API and exposed the /call-eureka-client endpoint. This endpoint prints the discovered service instance URL along with the response message returned from the rest template call.

Inside this method, we have used the Eureka Client instance, which is injected using the @Autowired annotation. This instance provides details about available registered service instances.

In our example, we have got the InstanceInfo of our registered service passing the service name my-service.

From the instanceInfo object, we are getting the base URL of the registered service and forming the actual service URL.

@SpringBootApplication
@EnableEurekaClient
@RestController
public class SpringBootEurekaClient2Application {
	@Autowired
	private EurekaClient eurekaClient;
	@Bean
	public RestTemplate RestTemplate() {
		return new RestTemplate();
	}
	@Autowired
	private RestTemplate restTemplate;
	public static void main(String[] args) {
		SpringApplication.run(SpringBootEurekaClient2Application.class, args);
	}
	@GetMapping("/call-eureka-client")
	public String method() {
		InstanceInfo instance = eurekaClient.getNextServerFromEureka("my-client", false);
		String response = restTemplate.getForObject(instance.getHomePageUrl() + "/call-me", String.class);
		return "Instance called is : " + instance.getHomePageUrl() + " <br/><br/> And Response : " + response;
	}
}

Start the service. We should be able to see the service registered on the eureka dashboard.

Services registered on eureka server

Access the service endpoint /call-eureka-client from the browser.

We should be able to access the my-client endpoint internally.

We will also get the instance discovered by the Eureka Client.

Finally, notice the discovered instance is different every time, by refreshing the page.

service discovery example
service discovery example
service discovery example

We have successfully implemented the service discovery with the Eureka Client.

Service discovery with Ribbon backed RestTemplate

Update the my-client service with the below changes.

Here, we are reading the application instance’s port number, and also returning it along with the response.

@SpringBootApplication
@EnableEurekaClient
@RestController
public class SpringBootEurekaClientApplication {
	@Value("${server.port}")
	private String serverPort;
	
	@GetMapping("/call-me")
	public String method() {
		return "You are calling me through service discovery!! with server port : " + serverPort;
	}
	public static void main(String[] args) {
		SpringApplication.run(SpringBootEurekaClientApplication.class, args);
	}
}

Update the my-client-2 service.

Here, we are creating a rest template bean along with the @LoadBalanced annotation. This annotation indicates that the rest template should use a RibbonLoadBalancerClient instance for interacting with other services.

@SpringBootApplication
@EnableEurekaClient
@RestController
public class SpringBootEurekaClient2Application {
	@Bean
	@LoadBalanced
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}
	@Autowired
	private RestTemplate restTemplate;
	public static void main(String[] args) {
		SpringApplication.run(SpringBootEurekaClient2Application.class, args);
	}
	@GetMapping("/call-eureka-client")
	public String method() {
		String response = restTemplate.getForObject("http://my-client/call-me/", String.class);
		return "Response : " + response;
	}
}

In the above code notice that we are using the rest template’s getForObject() method with the URL http://my-client/call-me/. Here, the my-client is the service id of the eureka client, which we are calling from the my-service-2.

The images below show the ribbon-backed service discovery application output.

The Ribbon load balancer balances the requests and passes the requests to the available instances of the registered eureka client in a round-robin fashion.

Eureka load balanced resttemplate example
Eureka load balanced resttemplate example
Eureka load balanced resttemplate example

That’s it. The explained code is available on Github.

Service discovery with Feign Client

We can also use Netflix’s feign client as an alternative to the spring ribbon-backed rest template.

Let us see how to use Netflix’s feign client library to call our service.

Add the spring-cloud-starter-openfeign dependency to the pom file.

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

Enable the feign client library by adding the annotation @EnableFeignClients to the spring boot application class.

@SpringBootApplication
@EnableFeignClients
@RestController
public class SpringBootFeignClientExampleApplication {
	//spring boot starter main method
}

While using the feign client, we create a Java interface and then use annotations to map the registered eureka service.

Spring dynamically creates a proxy class that will be used to invoke the service.

Let us create a Java interface as shown below.

@FeignClient("my-client")
public interface MyServiceFeignClient {
	@GetMapping("/call-me")
	public String method();
}

The @FeignClient annotation is used to set the eureka service’s application Id, which we are going to invoke. The my-client is our eureka service invoked by the feign client template. The method defined here is the same method present in the service.

We can also use the feign client to call the eureka service by auto-wiring it to our application.

Below is the complete code with the rest endpoint.

@SpringBootApplication
@EnableFeignClients
@RestController
public class SpringBootFeignClientExampleApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringBootFeignClientExampleApplication.class, args);
	}
	@Autowired
	MyServiceFeignClient myServiceFeignClient;
	@GetMapping("/call-eureka-client")
	public String method() {
		String response = myServiceFeignClient.method();
		return "Response : " + response;
	}
}

Run the eureka server, my-client service instances, and the feign client service.

Now, we should be able to invoke the my-client service from the feign client service.

Feign client example spring boot

That’s it. The explained code is available on Github.

Conclusion

In this article, we learned different ways of consuming a registered eureka service.

We learned how to use the Eureka Client, how to use the ribbon-backed Rest Template, and finally, how to use the Feign Client for service discovery.