Feign Service Consumer Implementation
Feign is a declarative web service client that simplifies HTTP API development. It uses annotations to define service interfaces and integrates seamlessly with Spring MVC.
Environment Setup
Required Components:
- Java 8+
- Spring Boot 2.1.1+
- Spring Cloud Finchley+
Dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
Service Registry Configuration
application.properties:
spring.application.name=feign-service-registry
server.port=8001
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.serviceUrl.defaultZone=http://localhost:8001/eureka/
Registry Server Class:
@EnableEurekaServer
@SpringBootApplication
public class ServiceRegistryApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRegistryApplication.class, args);
}
}
Feign Client Implementation
Consumer Configuration:
spring.application.name=feign-service-consumer
server.port=9002
eureka.client.serviceUrl.defaultZone=http://localhost:8001/eureka/
Consumer Application Class:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class FeignConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(FeignConsumerApplication.class, args);
}
}
Feign Client Interface:
@FeignClient(name = "target-service-provider")
public interface ServiceProxy {
@RequestMapping(value = "/greet")
String sendGreeting(@RequestParam(value = "user") String user);
}
Consumer Controller:
@RestController
public class ConsumerEndpoint {
@Autowired
ServiceProxy serviceProxy;
@RequestMapping("/greet/{user}")
public String forwardGreeting(@PathVariable("user") String user) {
return serviceProxy.sendGreeting(user);
}
}
Target Service Implementation
Target Service Configuration:
spring.application.name=target-service-provider
server.port=9003
eureka.client.serviceUrl.defaultZone=http://localhost:8001/eureka/
Target Service Controller:
@RestController
public class ServiceEndpoint {
@RequestMapping("/greet")
public String handleGreeting(@RequestParam String user) {
return user + ", Welcome!";
}
}
Ribbon Load Balancer Implementation
Ribbon provides client-side load balancing with configurable algorithms and connection management.
Dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
Load Balanced Client Setup
Consumer Configuration:
spring.application.name=ribbon-loadbalancer
server.port=9006
eureka.client.serviceUrl.defaultZone=http://localhost:8003/eureka/
Service Provider Configurations:
# Provider 1
spring.application.name=balanced-service
server.port=9007
# Provider 2
spring.application.name=balanced-service
server.port=9008
Load Balanced Client Application:
@SpringBootApplication
@EnableDiscoveryClient
public class RibbonClientApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonClientApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate balancedRestTemplate() {
return new RestTemplate();
}
}
Client Controller with Load Balancing:
@RestController
public class LoadBalancedController {
@Autowired
RestTemplate restTemplate;
@RequestMapping("/invoke")
public String callService() {
return restTemplate.getForObject(
"http://balanced-service/greet?name=developer",
String.class
);
}
}
Load Balancing Strategies
Ribbon supports multiple load balancing algorithms:
| Strategy | Description |
|---|---|
| RoundRobinRule | Sequential rotation through server list |
| RandomRule | Random server selection |
| WeightedResponseTimeRule | Selection based on response time weights |
| AvailabilityFilteringRule | Filters out servers with connectivity issues |
| ZoneAvoidanceRule | Considers zone performance and server availability |
Custom Strategy Configuartion:
Method 1 - Properties file:
balanced-service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
Method 2 - Configuration class:
@Configuration
public class CustomRibbonConfig {
@Bean
public IRule customRule() {
return new RandomRule();
}
}
@RibbonClient(
name = "balanced-service",
configuration = CustomRibbonConfig.class
)
public class ServiceConfiguration {
}
Manual Server List Configuration:
balanced-service.ribbon.listOfServers=localhost:9007,localhost:9008
Feign with Ribbon Integration
Feign automatically integrates with Ribbon for load balancing when multiple instances of the same service are registered.
Enhanced Feign Client with Load Balancing:
@FeignClient(name = "balanced-service")
public interface LoadBalancedProxy {
@RequestMapping(value = "/greet")
String distributedGreeting(@RequestParam(value = "name") String name);
}
Enhanced Controller:
@RestController
public class EnhancedController {
@Autowired
LoadBalancedProxy loadBalancedProxy;
@RequestMapping("/distributed/{name}")
public String loadBalancedCall(@PathVariable("name") String name) {
return loadBalancedProxy.distributedGreeting(name);
}
}