In-depth understanding of Feign

In-depth understanding of Feign

Feign: A powerful tool to simplify remote service calls

With the widespread application of microservice architecture, communication between services has become more and more complex, and Feign, as a lightweight HTTP client, simplifies the process of calling remote methods for us.

What is Feign?

Feign is a declarative web service client that can be used to simplify HTTP API calls. It is designed to make web service calls easier, whether locally or remotely. Feign allows developers to call remote services just like calling local services, providing a higher level of abstraction and shielding the details of underlying HTTP communication.

Feign's advantages

  1. Declarative API definition

    One of the highlights of Feign is the use of declarative API definition. Through simple annotations, developers can define the API interface of the remote service that needs to be called. This declarative style makes the code clearer and easier to read, and reduces the user's learning cost.

    @FeignClient(name = "example-service")
    public interface ExampleServiceClient {
          
          
    
        @GetMapping("/api/resource")
        String getResource();
    
    }
    
  2. Integrated load balancing

    In a microservices architecture, load balancing is an essential component. Feign natively supports load balancing and integrates the Ribbon load balancer to make service calls more robust and reliable.

  3. Automated service discovery

    Feign automatically performs service discovery through service names, eliminating the need to manually specify the IP address and port of the remote service. This automated service discovery mechanism makes the deployment and expansion of microservices more flexible.

Using Feign to make remote service calls

First, we need to introduce Feign's dependencies into the project:

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

Then, we create a Feign client interface and define the remote service API that needs to be called through annotations:

@FeignClient(name = "example-service")
public interface ExampleServiceClient {
    
    
    
    @GetMapping("/api/resource")
    String getResource();
}

In this example, @FeignClientthe annotation identifies this as a Feign client interface, and namethe properties specify the name of the remote service that needs to be called.

Next, we inject and use this Feign client in the business logic:

@RestController
public class ExampleController {
    
    
    
    @Autowired
    private ExampleServiceClient exampleServiceClient;
    
    @GetMapping("/consume-resource")
    public String consumeResource() {
    
    
        return exampleServiceClient.getResource();
    }
}

With such a simple configuration, we can call remote services just like calling local services. Feign handles all HTTP communication details under the hood, including load balancing and service discovery.

Feign’s advanced features and best practices

1. Circuit breaker mechanism

In a microservice architecture, the failure of one service may lead to instability of the entire system. In order to deal with this situation, Feign has integrated a circuit breaker mechanism that can trigger circuit breaker when a service call fails to avoid continued requests for failed services.

By using Hystrix as a circuit breaker, we can easily enable circuit breaking in Feign:

@FeignClient(name = "example-service", fallback = ExampleServiceFallback.class)
public interface ExampleServiceClient {
    
    
    
    @GetMapping("/api/resource")
    String getResource();
}

In the above code, fallbackthe attribute specifies the downgrade handling class when the call fails. For example, we can create a ExampleServiceFallbackclass, implement ExampleServiceClientthe interface, and define the downgrade logic in it:

@Component
public class ExampleServiceFallback implements ExampleServiceClient {
    
    
    
    @Override
    public String getResource() {
    
    
        return "Fallback Resource";
    }
}

The introduction of the circuit breaker mechanism can improve the stability and fault tolerance of the system and ensure graceful degradation in the face of service failures.

2. Request to retry

Feign also supports request retries to deal with some short-term network fluctuations or service instability. feign.RetryerEnable request retry mechanism through configuration :

feign:
  client:
    config:
      default:
        retryer: com.example.CustomRetryer

Among them, CustomRetryerit is a custom retryer class that can be configured according to the actual needs of the project. For example:

public class CustomRetryer implements Retryer {
    
    

    private final int maxAttempts;
    private final long period;
    private final long maxPeriod;

    public CustomRetryer() {
    
    
        this(100, 1000, 3);
    }

    public CustomRetryer(long period, long maxPeriod, int maxAttempts) {
    
    
        this.period = period;
        this.maxPeriod = maxPeriod;
        this.maxAttempts = maxAttempts;
    }

    @Override
    public void continueOrPropagate(RetryableException e) {
    
    
        if (e.getCause() instanceof CustomException) {
    
    
            throw (CustomException) e.getCause();
        }
        throw e;
    }

    @Override
    public Retryer clone() {
    
    
        return new CustomRetryer(period, maxPeriod, maxAttempts);
    }
}

3. Custom configuration

Feign provides a wealth of custom configuration options to meet the needs of different scenarios. Global configuration can be done through FeignClientsConfigurationthe class FeignClientSpecification:

@Configuration
public class FeignConfiguration {
    
    

    @Bean
    public FeignClientSpecification feignClientSpecification() {
    
    
        return new FeignClientSpecification();
    }
}

And application.ymlmake relevant configurations in the file:

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000

In the above example, we set the default connection timeout and read timeout.

4. Logging

Feign also supports detailed request and response logging to facilitate debugging and monitoring by developers. application.ymlFeign's logging can be turned on through the log level in the configuration file:

logging:
  level:
    com.example.feign.ExampleServiceClient: DEBUG

This way, Feign will print detailed HTTP request and response logs when calling the remote service.

Feign performance optimization and integration practice

1.Performance optimization strategy

In order to ensure high performance in large-scale microservice systems, we need to consider some performance optimization strategies. Here are some common Feign performance optimization suggestions:

a. Tuning of connection pool

Feign uses an underlying HTTP client (usually Apache HttpClient or OkHttp). By adjusting these client connection pool parameters, you can optimize connection reuse and performance. For example, you can set the maximum number of connections, the maximum number of connections per route, the connection timeout, etc.

httpclient:
  maxConnections: 200
  maxConnectionsPerRoute: 50
  connectionTimeout: 3000
  readTimeout: 5000
b. Close unnecessary logs

While Feign's logging is helpful for debugging and monitoring, turning on too many logs in a production environment can impact performance. It is recommended to set Feign's log level to or higher in a production environment INFOto avoid excessive log output.

logging:
  level:
    com.example.feign.ExampleServiceClient: INFO
c. Reasonable use of timeout settings

In Feign, control the connection timeout and read timeout by setting connectTimeoutand readTimeout. Reasonable settings can ensure the stability of the service while avoiding excessive waiting times.

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000

2. Integration with other microservice frameworks

In actual microservice systems, multiple microservice frameworks are usually used to meet different needs. Feign can be integrated with other frameworks to better serve the entire microservices ecosystem.

a. Integrate with Spring Cloud Sleuth

Spring Cloud Sleuth is a distributed tracking solution of Spring Cloud. By integrating Sleuth, request tracking and tracing can be realized between microservices.

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

By adding annotations on the Feign client's interface @NewSpan, new traces can be created when called across services:

@FeignClient(name = "example-service")
public interface ExampleServiceClient {
    
    
    
    @NewSpan
    @GetMapping("/api/resource")
    String getResource();
}
b. Integrate with Resilience4j

Resilience4j is an excellent lightweight fault-tolerant library. By integrating with Feign, it can provide more flexible and fine-grained circuit breaker, retry, current limiting and other functions.

<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-spring-cloud2</artifactId>
    <version>1.7.0</version>
</dependency>

@CircuitBreakerBy adding annotations such as , etc. to the interface of the Feign client @Retry, the corresponding fault-tolerance strategy can be easily implemented.

5. Practical experience and best practices

a.Interface version management

In a microservice architecture, iterative upgrades of services are inevitable. In order to prevent incompatibility issues in service calls, it is recommended to use interface version management. @RequestMappingWhen Feign uses annotations on the interface , you can specify the media types of the request and response through the producesand consumesattributes. This way, even if the interface changes, different versions of the interface can coexist.

@FeignClient(name = "example-service")
@RequestMapping(value = "/api", produces = "application/vnd.example.v1+json")
public interface ExampleServiceClientV1 {
    
    
    
    @GetMapping("/resource")
    String getResource();
}
b. Reasonable use of Fallback

The circuit breaker mechanism is an important means to ensure system stability, and fallback is the degradation process when circuit breaker occurs. When designing fallback logic, you should ensure that the downgraded operation does not cause more serious problems. For example, in Feign's Fallback logic, you can return default values ​​or cache data to avoid affecting the normal operation of the entire system.

@Component
public class ExampleServiceFallback implements ExampleServiceClient {
    
    
    
    @Override
    public String getResource() {
    
    
        return "Fallback Resource";
    }
}
c. Asynchronous calls and concurrency control

In high-concurrency scenarios, synchronous calls may cause system performance problems. CompletableFutureFeign supports asynchronous calls and can achieve non-blocking remote service calls by using other methods. In addition, for frequently called interfaces, you can consider implementing concurrency control to prevent the system from being overwhelmed by too many requests.

@FeignClient(name = "example-service")
public interface ExampleServiceClient {
    
    
    
    @Async
    @GetMapping("/resource")
    CompletableFuture<String> getResource();
}
d. Set a reasonable timeout period

The call of remote services may be affected by factors such as network fluctuations and server load. Therefore, setting a reasonable timeout is the key to ensuring system stability. A timeout that is too long may cause the system to respond slowly, and a timeout that is too short may cause unnecessary fuses. According to the actual situation, it is necessary to set reasonable connection timeout and read timeout.

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000

6. Security considerations and practices

In a microservices architecture, security is a crucial consideration. As a tool for remote service calls, Feign also needs to consider how to ensure data security and system defense.

a. Use HTTPS protocol

In a production environment, it is strongly recommended to use the HTTPS protocol for remote service calls to ensure data encryption during transmission. @RequestMappingThe protocol can be specified by using annotations on the Feign client interface https:

@FeignClient(name = "example-service")
@RequestMapping(value = "/api", produces = "application/json", protocol = "https")
public interface ExampleServiceClient {
    
    
    
    @GetMapping("/resource")
    String getResource();
}
b. Security authentication and authorization

In a microservice architecture, communication between services may involve sensitive data, so it is necessary to add security authentication and authorization to Feign. You can use security frameworks such as Spring Security to authenticate by adding tokens or other security credentials to the request header of the Feign client.

@FeignClient(name = "example-service")
public interface ExampleServiceClient {
    
    
    
    @GetMapping("/resource")
    String getResource(@RequestHeader("Authorization") String token);
}
c. Prevent CSRF attacks

In order to prevent cross-site request forgery (CSRF) attacks, it is recommended to add the CSRF token to the Feign client's request and ensure that the server performs effective CSRF verification.

@FeignClient(name = "example-service")
public interface ExampleServiceClient {
    
    
    
    @GetMapping("/resource")
    String getResource(@RequestHeader("X-CSRF-Token") String csrfToken);
}
d.Log security

In a production environment, Feign's logs may contain sensitive information, such as request parameters, URLs, etc. It is recommended to turn off or limit Feign's log output level in the production environment to prevent sensitive information from being leaked.

logging:
  level:
    com.example.feign.ExampleServiceClient: INFO

7. Performance monitoring and logging

In order to detect potential performance problems and failures in a timely manner, it is recommended to add performance monitoring and logging to Feign. You can use monitoring tools such as Spring Boot Actuator to monitor Feign's calls. At the same time, properly configure Feign's logging level to obtain useful information during debugging and troubleshooting.

management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    feign:
      sensitive: false

Guess you like

Origin blog.csdn.net/qq_51447496/article/details/135433680