Spring Cloud OpenFeign: Declarative Service Calls Based on Ribbon and Hystrix

SpringBoot e-commerce project mall (20k+star) address: https://github.com/macrozheng/mall

abstract

Spring Cloud OpenFeign is a declarative service invocation tool, which integrates Ribbon and Hystrix and has load balancing and service fault tolerance functions. This article will introduce its usage in detail.

Feign introduction

Feign is a declarative service invocation tool. We can invoke a service interface by creating an interface and configuring it with annotations, which simplifies the development of invoking a service interface directly using RestTemplate. Feign has pluggable annotation support, as well as support for Feign annotations, JAX-RS annotations and Spring Mvc annotations. When using Feign, Spring Cloud integrates Ribbon and Eureka to provide load-balanced service invocation and Hystrix-based service fault-tolerant protection.

Create a feign-service module

Here we create a feign-service module to demonstrate the common functions of feign.

Adding dependencies to pom.xml

<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>

Configuration in 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/

Add the @EnableFeignClients annotation on the startup class to enable Feign's client functionality

@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class FeignServiceApplication {

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

}

Adding UserService Interface to Complete Interface Binding of UserService Service Service

We implemented a Feign client through the @FeignClient annotation, in which the value is user-service, which means that this is the interface calling client for the user-service service. We can recall the User Controller in user-service, just change it to an interface and keep the original Spring Mvc annotation.

/**
 * Created by macro on 2019/9/5.
 */
@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);
}

Adding UserFeignController to invoke UserService to implement service invocation

/**
 * Created by macro on 2019/8/29.
 */
@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);
    }
}

Demonstration of Load Balancing Function

  • Start eureka-service, two user-service and feign-service services. After startup, the registry is shown as follows:

  • Multiple calls http://localhost:8701/user/1 Tests show that user-service services running in 8201 and 8202 alternately print the following information:
2019-10-04 15:15:34.829 INFO 9236 - - [nio-8201-exec-5] c.macro.cloud.controller.UserController: Get user information according to id, user name is macro:
2019-10-04 15:15:35.492 INFO 9236 - - [io-8201-exec-10] c.macro.cloud.controller.UserController: Get user information according to id, user name is macro:
2019-10-04 15:15:35.825 INFO 9236 - - [nio-8201-exec-9] c.macro.cloud.controller.UserController: Get user information according to id, user name is macro:

Service degradation in Feign

Service degradation in Feign is very convenient to use. Just add an implementation class for service degradation processing to the interface defined by Feign client. Next, we add a service degradation implementation class for UserService interface.

Adding the Service Degradation Implementation Class UserFallbackService

It should be noted that it implements the UserService interface and implements the service degrading logic for each implementation method in the interface.

/**
 * Created by macro on 2019/9/5.
 */
@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("The call failed and the service was degraded",500);
    }

    @Override
    public CommonResult delete(Long id) {
        return new CommonResult("The call failed and the service was degraded",500);
    }
}

Modify the UserService interface and set the service degradation processing class to UserFallbackService

Modify the parameters in the @FeignClient annotation and set fallback to UserFallbackService.class.

@FeignClient(value = "user-service",fallback = UserFallbackService.class)
public interface UserService {
}

Modify application.yml to turn on Hystrix functionality

feign:
  hystrix:
    enabled: true #Open Hystrix in Feign

Demonstration of Service Degradation Function

  • Close two user-service services and restart feign-service;
  • call http://localhost:8701/user/1 Testing shows that service degradation information is returned.

Log Printing Function

Feign provides logging printing, and we can adjust the log level by configuring it to understand the details of Http requests in Feign.

log level

  • NONE: By default, no logs are displayed;
  • BASIC: Only request method, URL, response status code and execution time are recorded.
  • HEADERS: In addition to the information defined in BASIC, there are headers for requests and responses.
  • FULL: In addition to the information defined in HEADERS, there are also the body and metadata of requests and responses.

Open more detailed logs through configuration

We use the java configuration to enable Feign to print the most detailed Http request log information.

/**
 * Created by macro on 2019/9/5.
 */
@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

Configure the Feign client that needs to open the log in application.yml

The log level for configuring UserService is debug.

logging:
  level:
    com.macro.cloud.service.UserService: debug

view log

call http://localhost:8701/user/1 For testing, you can see the following logs.

2019-10-04 15:44:03.248 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService      : [UserService#getUser] ---> GET http://user-service/user/1 HTTP/1.1
2019-10-04 15:44:03.248 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService      : [UserService#getUser] ---> END HTTP (0-byte body)
2019-10-04 15:44:03.257 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService      : [UserService#getUser] <--- HTTP/1.1 200 (9ms)
2019-10-04 15:44:03.257 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService      : [UserService#getUser] content-type: application/json;charset=UTF-8
2019-10-04 15:44:03.258 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService      : [UserService#getUser] date: Fri, 04 Oct 2019 07:44:03 GMT
2019-10-04 15:44:03.258 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService      : [UserService#getUser] transfer-encoding: chunked
2019-10-04 15:44:03.258 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService      : [UserService#getUser] 
2019-10-04 15:44:03.258 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService      : [UserService#GetUser] {"data": {"id": 1, "username", "macro", "password", "123456"}, "message", "operation success", "code":200}
2019-10-04 15:44:03.258 DEBUG 5204 --- [-user-service-2] com.macro.cloud.service.UserService      : [UserService#getUser] <--- END HTTP (92-byte body)

Common configuration of Feign

Feign's own configuration

feign:
  hystrix:
    enabled: true #Open Hystrix in Feign
  compression:
    request:
      enabled: false #Whether GZIP compression is applied to requests
      mime-types: text/xml,application/xml,application/json #Specify the compressed request data type
      min-request-size: 2048 #Requests that exceed this size are compressed
    response:
      enabled: false #Whether to Compress the Response with GZIP
logging:
  level: #Modify Log Level
    com.macro.cloud.service.UserService: debug

Ribbon configuration in Feign

Configuring Ribbon in Feign can directly use Ribbon's configuration for reference. Spring Cloud Ribbon: Load-balanced service invocation.

Hystrix configuration in Feign

Configuring Hystrix in Feign can directly use the configuration of Hystrix for reference. Spring Cloud Hystrix: Service Fault Tolerant Protection.

Modules used

springcloud-learning
├── eureka-server -- eureka Registry Center
├── user-service -- provide User object CRUD Interface services
└── feign-service -- feign Service invocation test service

Project source address

https://github.com/macrozheng/springcloud-learning

Public address

mall project In the whole series of learning courses, we pay attention to the first time acquisition of the public number.

Keywords: Java Spring xml github JSON

Added by samshel on Sun, 13 Oct 2019 21:25:16 +0300