“This is the 14th day of my participation in the More Text Challenge. For more details, see more Text Challenge.”
What is OpenFeign
Feign is a declarative Web Service client. It is a declarative, template-based HTTP client. Spring Cloud supports Spring MVC annotations, such as @requesMapping, on the basis of Feign. OpenFeign’s @FeignClient can parse the interface under SpringMVC’s @RequestMapping annotation and use dynamic proxy to generate implementation classes that perform load balancing and invoke other services. Feign can hide Rest requests and pretend to be similar to SpringMVC’s Controller. You don’t have to concatenate urls, concatenate parameters, etc., all of that is done by Feign.
- Pluggable annotation support, including Feign annotations and JSX-RS annotations
- Support pluggable HTTP encoders and decoders
- Support for Hystrix and its Fallback
- Supports load balancing in the Ribbon
- Support for compression of HTTP requests and responses.
Introduction to OpenFeign
Create parent Pom project: cloud-Openfeign-Practice
This project is used to house all the openFeign examples.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.msr.better</groupId>
<artifactId>cloud-openfeign-practice</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.3. RELEASE</version>
<relativePath/> <! -- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring.cloud-version>Hoxton.SR3</spring.cloud-version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Copy the code
Create the module: cloud-OpenFeign-HehlLO
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
Copy the code
The configuration file
application.xml
server:
port: 8010
spring:
application:
name: openfeign-hello
# log
logging:
level:
com.msr.better.feign.service.HelloFeignService: debug
Copy the code
The configuration class
@Configuration
public class HelloFeignServiceConfig {
/** * Logger.Level Specifies the following levels: * NONE: records no information * BASIC: records only the request method, URL, response status code, and execution time * HEADERS: In addition to BASIC level information, request and response header information is also recorded. * FULL: Records details of all requests and responses, including header information, request body, and metadata */
@Bean
Logger.Level feignLoggerLevel(a) {
returnLogger.Level.FULL; }}Copy the code
serivce
@FeignClient(name = "github-client", url = "https://api.github.com", configuration = HelloFeignServiceConfig.class)
public interface HelloFeignService {
/**
* content:
* {
* "message":"Validation Failed",
* "errors":[{"resource":"Search","field":"q","code":"missing"}],
* "documentation_url":"https://developer.github.com/v3/search"
* }
*
* @param queryStr
* @return* /
@GetMapping(value = "/search/repositories")
String searchRepo(@RequestParam("q") String queryStr);
}
Copy the code
In HelloFeignService above, the @feignClient annotation manually specifies the URL(api.github.com) to be accessed by the interface. When calling the searchGithubRepoByStr method, Eventually a GET request will be made https://api.github…
controller
@RestController
public class HelloFeignController {
@Autowired
private HelloFeignService helloFeignService;
@GetMapping(value = "/search/github")
public String searchGithubRepoByStr(@RequestParam("searchStr") String searchStr) {
returnhelloFeignService.searchRepo(searchStr); }}Copy the code
Start the class
@SpringBootApplication
@EnableFeignClients
public class OpenFeignHelloApplication {
public static void main(String[] args) { SpringApplication.run(OpenFeignHelloApplication.class, args); }}Copy the code
When the @enableFeignClients package is scanned, all @FeignClients are scanned.
Start the test
Run to start the class, in your browser or the PostMan tools like http://localhost:8010/search/github? searchStr=spring-cloud
How OpenFeign works
- Add the @enableFeignClients annotation to enable scanning and loading of the @FeignClient annotation. According to the development specification of Feign Client, define the interface and add @Feiginclient annotation
- When the program starts, a package scan is performed to scan all @FeignClient annotated interfaces and inject this information into the IOC container. When the defined Feign interface is called, a specific RequestTemplate is generated using the JDK’s proxy. Feign creates a RequestTemplate object for each interface method. This object encapsulates all the information required for an HTTP request, such as the request parameter name, request method, and so on.
- The Request is then generated by the RequestTemplate and handed over to a Client, which can be a JDK native URLConnection, HttpClient, or Okhttp. Finally, the Client is encapsulated in the LoadBalanceClient class. The name of this class can be seen as a combination of the Ribbon load balancing to make calls between services. OpenFeign has the Ribbon integrated by default.
Basic functions of OpenFiegn
Parse @FeignClient annotations
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interfaceFeignClient {... }Copy the code
As you can see from the FeignClient annotation, elementType. TYPE indicates that the function of FeignClient is the interface. Its common attributes are as follows:
- Name: The name of the execution FeignClient. If the Ribbon is used in a project, the name attribute is used as the name of the microservice, which is used for service discovery.
- Url: Urls are generally used for debugging, and you can manually specify the address for @feignClient calls
- Decode404: When a 404 error occurs, if this field is true, decoder is called to decode, otherwise FeignException is thrown.
- Configuration: Feigin configuration class, you can customize Encode, Decode, LogLevel, Contract of Feign.
- Fallback: Defines a fault-tolerant class that will invoke the fault-tolerant Roger of a remote interface when it fails or times out. Fallback classes must implement the @FeignClient flag. Found in OpenFeign’s dependencies, integrated with Hystrix.
- FallbackFactory: Factory class used to generate instances of fallback classes. This property enables common fault-tolerant logic for each interface to reduce duplication of code.
- Path: Defines the uniform prefix of the current FeignClient.
OpenFeign starts GZIP compression
OpenFeign supports GZIP compression of requests and responses to provide communication efficiency. You only need to configure it in the configuration file, which is relatively simple.
server:
port: 8011
spring:
application:
name: openfeign-gzip
logging:
level:
com.msr.better.feign.service.HelloFeignService: debug
feign:
# Compression configuration
compression:
request:
enabled: true
# Configure the MIME TYPE supported by compression
mime-types: text/xml,application/xml,application/json
min-request-size: 2048 Configure a lower limit for the compressed data size
response:
enabled: true # Configure response GZIP compression
Copy the code
Equivalent properties configuration
feign.compression.request.enabled=true
# Configure the MIME TYPE supported by compression
feign.compression.request.mime-types=text/xml,application/xml,application/json
Configure a lower limit for the compressed data size
feign.compression.request.min-request-size=2048
# Configure response GZIP compression
feign.compression.response.enabled=true
Copy the code
Supports property file configuration
Configure a single FeignClient with a specific name
The configuration information for @feignClientde can be configured as a configuration file
server:
port: 8011
spring:
application:
name: openfeign-gzip
logging:
level:
com.msr.better.feign.service.HelloFeignService: debug
feign:
# Compression configuration
compression:
request:
enabled: true
# Configure the MIME TYPE supported by compression
mime-types: text/xml,application/xml,application/json
min-request-size: 2048 Configure a lower limit for the compressed data size
response:
enabled: true # Configure response GZIP compression
client:
config:
# FeignName to be configured
github-client:
# Connection timeout
connectTimout: 5000
# Read timeout
readTimeut: 5000
# Feign log level
loggerLevel: full
# Feign error decoder
errorDecode: com.example.SimpleErrorDecoder
# Set retry
retryer: com.example.SimpleRetryer
# before
requestInterceptors:
- com.example.FirstInterceptor
- com.example.SecondInterceptor
decode404: false
# Feign encoder
encoder: com.example.SimpleEncoder
# Feign decoder
decoder: com.example.SimpleDecoder
Contract configuration for # Feign
contract: com.example.SimpleContract
Copy the code
This applies to all FeignClient configurations
Have a defaultConfiguration attribute in @ EnableFeignClients annotation, the default Settings can be written as a configuration class, such as the class is called DefaultFeignClientConfiguration.
@SpringBootApplication
@EnableFeignClients(defaultConfiguration = DefaultFeignClientConfiguration.class)
public class FeignClientConfigApplication{
SpringApplication.run(FeignClientConfigApplication.class, args);
}
Copy the code
You can also configure it in the configuration file
feign:
client:
config:
default:
# Connection timeout
connectTimout: 5000
# Read timeout
readTimeut: 5000
# Feign log level
loggerLevel: full
.
Copy the code
However, if you configure FeignClient’s global configuration both in the configuration file and in the annotations, the configuration file overrides the way the configuration class is executed on the annotations. However, you can change the priority of the Feigin configuration by adding feign.client.default-to-properties=false to the configuration file.
FeignClient enables logging
In fact, the above is already configured FeignClient logging. Feign provides an instance of Fegin.Logger for each Feign. It is easy to enable log output in the configuration.
Step 1: Configure log output in the configuration file
logging:
level:
# Specify which FeignClient interface requests need to output logs, and the log level
com.msr.better.feign.service.HelloFeignService: debug
Copy the code
Step 2: Configure the log Bean in the main program entry using Java code
@Bean
Logger.Level feignLoggerLevel(a) {
return Logger.Level.FULL;
}
Copy the code
Alternatively, you can configure the class through the configuration class and perform the configuration class changes in the @FeignClient annotation.
@Configuration
public class HelloFeignServiceConfig {
/** * Logger.Level Specifies the following levels: * NONE: records no information * BASIC: records only the request method, URL, response status code, and execution time * HEADERS: In addition to BASIC level information, request and response header information is also recorded. * FULL: Records details of all requests and responses, including header information, request body, and metadata */
@Bean
Logger.Level feignLoggerLevel(a) {
returnLogger.Level.FULL; }}Copy the code
FeignClient timeout configuration
Feign calls are divided into two layers, the Ribbon calls and the Hystrix calls. However, higher versions of Hystrix are turned off by default. Read timed out executing POST http://*** is an exception caused by the Ribbon. In this case, the Ribbon can be properly timed out
ribbon:
ConnectTimeout: 2000
ReadTimeout: 5000
Copy the code
HystrixRuntimeException: XXX timed -out and no fallback available . This is the Hystrix timeout error
feign:
hystrix:
enabled: true
Set hystrix timeout
hystrix:
shareSecurityContext: true
command:
default:
circuitBreaker:
sleepWindowinMilliseconds: 10000
forceClosed: true
execution:
isolation:
thread:
timeoutinMilliseconds: 10000
Copy the code