Mastering Spring Cloud OpenFeign: From Setup to Fault Tolerance
This article introduces Spring Cloud OpenFeign, explains its declarative service call features, walks through creating a feign-service module with Maven dependencies, configuring Eureka and Ribbon, defining Feign clients, demonstrating load balancing, implementing Hystrix fallback, and enabling detailed logging for robust microservice communication.
Feign Introduction
Feign is a declarative service‑call tool; by defining an interface and annotating it you can invoke remote services without using RestTemplate directly. Spring Cloud integrates Ribbon and Eureka for load‑balanced calls and Hystrix for circuit‑breaker protection.
Create a feign-service Module
We create a feign-service module to demonstrate common Feign features.
Add Maven Dependencies
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>Configure application.yml
server:
port: 8701
spring:
application:
name: feign-service
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8001/eureka/Enable Feign Clients
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class FeignServiceApplication {
public static void main(String[] args) {
SpringApplication.run(FeignServiceApplication.class, args);
}
}Define UserService Interface
Using @FeignClient(value="user-service") creates a Feign client for the user-service service.
@FeignClient(value = "user-service")
public interface UserService {
@PostMapping("/user/create")
CommonResult create(@RequestBody User user);
@GetMapping("/user/{id}")
CommonResult<User> getUser(@PathVariable Long id);
@GetMapping("/user/getByUsername")
CommonResult<User> getByUsername(@RequestParam String username);
@PostMapping("/user/update")
CommonResult update(@RequestBody User user);
@PostMapping("/user/delete/{id}")
CommonResult delete(@PathVariable Long id);
}Implement UserFeignController
@RestController
@RequestMapping("/user")
public class UserFeignController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public CommonResult getUser(@PathVariable Long id) {
return userService.getUser(id);
}
@GetMapping("/getByUsername")
public CommonResult getByUsername(@RequestParam String username) {
return userService.getByUsername(username);
}
@PostMapping("/create")
public CommonResult create(@RequestBody User user) {
return userService.create(user);
}
@PostMapping("/update")
public CommonResult update(@RequestBody User user) {
return userService.update(user);
}
@PostMapping("/delete/{id}")
public CommonResult delete(@PathVariable Long id) {
return userService.delete(id);
}
}Load‑Balancing Demonstration
Start eureka-service, two instances of user-service, and feign-service. The registry shows all services.
Repeatedly call http://localhost:8701/user/1; the requests are distributed between the two user-service instances, as seen in the logs.
Feign Service Degradation (Fallback)
Feign makes service degradation easy: just provide an implementation of the Feign client interface that supplies fallback logic.
Add Fallback Implementation UserFallbackService
The class implements UserService and returns default responses for each method.
@Component
public class UserFallbackService implements UserService {
@Override
public CommonResult create(User user) {
User defaultUser = new User(-1L, "defaultUser", "123456");
return new CommonResult<>(defaultUser);
}
@Override
public CommonResult<User> getUser(Long id) {
User defaultUser = new User(-1L, "defaultUser", "123456");
return new CommonResult<>(defaultUser);
}
@Override
public CommonResult<User> getByUsername(String username) {
User defaultUser = new User(-1L, "defaultUser", "123456");
return new CommonResult<>(defaultUser);
}
@Override
public CommonResult update(User user) {
return new CommonResult("调用失败,服务被降级", 500);
}
@Override
public CommonResult delete(Long id) {
return new CommonResult("调用失败,服务被降级", 500);
}
}Configure Fallback in @FeignClient
Set the fallback attribute to UserFallbackService.class .
@FeignClient(value = "user-service", fallback = UserFallbackService.class)
public interface UserService { }Enable Hystrix in application.yml
feign:
hystrix:
enabled: trueService Degradation Demo
Stop both user-service instances and restart feign-service.
Calling http://localhost:8701/user/1 returns the fallback response.
Logging Feature
Feign provides configurable logging levels to inspect HTTP request details.
Logging Levels
NONE – no logs.
BASIC – method, URL, status, time.
HEADERS – BASIC plus request/response headers.
FULL – HEADERS plus body and metadata.
Enable Full Logging via Java Config
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}Set Logging Level for Specific Client in application.yml
logging:
level:
com.macro.cloud.service.UserService: debugView Logs
Calling http://localhost:8701/user/1 shows detailed request/response logs.
2019-10-04 15:44:03.248 DEBUG ... [UserService#getUser] --> GET http://user-service/user/1 HTTP/1.1
... (full log omitted for brevity)Common Feign Configurations
Feign‑specific Settings
feign:
hystrix:
enabled: true
compression:
request:
enabled: false
mime-types: text/xml,application/xml,application/json
min-request-size: 2048
response:
enabled: false
logging:
level:
com.macro.cloud.service.UserService: debugRibbon Configuration in Feign
Feign can use Ribbon’s load‑balancing settings directly; refer to Spring Cloud Ribbon documentation.
Hystrix Configuration in Feign
Hystrix settings are the same as in Spring Cloud Hystrix; refer to its documentation.
Modules Used
springcloud-learning
├── eureka-server // Eureka registry
├── user-service // Provides CRUD APIs for User objects
└── feign-service // Demonstrates Feign service callsSigned-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
