Service Discovery
- Service Discovery Using Eureka
- Spring Cloud - Creating Eureka Server
- Spring Cloud - Creating Eureka Client
- Eureka Client Consumer Example
- Spring Cloud - Eureka Server API
- Spring Cloud - Eureka High Availablity
- Spring Cloud - Eureka Zone Awareness
Synchronous Communication
- Synchronous Communication with Feign Client
- Spring Cloud - Feign Client with Eureka
- Spring Cloud - Testing Feign Client
Synchronous Communication
- Spring Cloud - Gateway
- Spring Cloud - Creating Gateway Application
- Spring Cloud - Testing Gateway Application
- Spring Cloud - Monitoring Gateway Application
Miscellaneous
- Spring Cloud - Load Balancer
- Circuit Breaker using Hystrix
- Streams with Apache Kafka
- Distributed Logging using ELK and Sleuth
Spring Cloud Useful Resources
Synchronous Communication with Feign Client
Introduction
In a distributed environment, services need to communicate with each other. The communication can either happen synchronously or asynchronously. In this section, we will look at how services can communicate by synchronous API calls.
Although this sounds simple, as part of making API calls, we need to take care of the following −
Finding address of the callee − The caller service needs to know the address of the service which it wants to call.
Load balancing − The caller service can do some intelligent load balancing to spread the load across callee services.
Zone awareness − The caller service should preferably call the services which are in the same zone for quick responses.
Netflix Feign and Spring RestTemplate (along with Ribbon) are two well-known HTTP clients used for making synchronous API calls. In this tutorial, we will use Feign Client.
Feign Dependency Setting
In order to use Feign Client API, we need to update the pom.xml of the client service with the following dependency −
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
Enable Feign Clients
And then, annotate our Spring application class with the correct annotation, i.e., @EnableDiscoveryClient and @EnableFeignCLient
package com.tutorialspoint;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class RestaurantService{
public static void main(String[] args) {
SpringApplication.run(RestaurantService.class, args);
}
}
Points to note in the above code −
@ EnableDiscoveryClient − This is the same annotation which we use for reading/writing to the Eureka server.
@EnableFeignCLient − This annotation scans our packages for enabled feign client in our code and initializes it accordingly.
Once done, now let us look briefly at Feign Interfaces which we need to define the Feign clients.
Using Feign Interfaces for API calls
Feign client can be simply setup by defining the API calls in an interface which can be used in Feign to construct the boilerplate code required to call the APIs. For example, consider we have two services −
Service A − Caller service which uses the Feign Client.
Service B − Callee service whose API would be called by the above Feign client
The caller service, i.e., service A in this case needs to create an interface for the API which it intends to call, i.e., service B.
package com.tutorialspoint;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(name = "service-B")
public interface ServiceBInterface {
@RequestMapping("/objects/{id}", method=GET)
public ObjectOfServiceB getObjectById(@PathVariable("id") Long id);
@RequestMapping("/objects/", method=POST)
public void postInfo(ObjectOfServiceB b);
@RequestMapping("/objects/{id}", method=PUT)
public void postInfo((@PathVariable("id") Long id, ObjectOfBServiceB b);
}
Points to note −
The @FeignClient annotates the interfaces which will be initialized by Spring Feign and can be used by rest of the code.
Note that the FeignClient annotation needs to contain the name of the service, this is used to discover the service address, i.e., of service B from Eureka or other discovery platforms.
We can then define all the API function name which we plan to call from service A. This can be general HTTP calls with GET, POST, PUT, etc., verbs.
Once this is done, service A can simply use the following code to call the APIs of service B −
@Autowired ServiceBInterface serviceB . . . ObjectOfServiceB object = serviceB. getObjectById(5);