The fastest shortcut in the world is to keep your feet on the ground. Focus on the sharing place.
Finchley.SR2
What is Feign
Feign is a declarative Web client that can create interfaces using its annotations and also supports custom codecs. Spring Cloud integrates Ribbon and Eureka to provide load balancing policies for clients. Feing has two main annotations: @enableFeignClients for enabling feIGN functionality and @FeignClient for defining the FEIGN interface.
Introduce Feign
1. Increase dependency
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
Copy the code
2, Example spring Boot app
@SpringBootApplication @EnableFeignClients public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}Copy the code
StoreClient.java
@FeignClient("stores")
public interface StoreClient {
@RequestMapping(method = RequestMethod.GET, value = "/stores")
List<Store> getStores();
@RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
Store update(@PathVariable("storeId") Long storeId, Store store);
}
Copy the code
In the @feignClient annotation this (“stores”) parameter is a unique name (which is usually the service name) used to create the Ribbon’s load balancer. You can also use url parameters on annotations (find an absolute path, such as www.xxx.com).. The Ribbon client will find physical addresses based on (“stores”), find services in its registry if Eureka is used, and configure an external list if not.
Override the default Feign properties
Feign components as long as be @ FeignClient statement is a client, we can through the use of FeignClientsConfiguration create our custom configuration items, Decoder, a feign.Encoder, and a feign.contract.example
@FeignClient(name = "stores", configuration = FooConfiguration.class)
public interface StoreClient {
//..
}
Copy the code
In this demo client comprised FeignClientsConfiguration and FooConfiguration two combination (configuration will cover at the front of the back)
The FooConfiguration class does not require the @Configuration annotation. If you add this you also need to exclude it when you use @ComponentScan. Otherwise it will be feign.decoder, feign.encoder, feign.contract default.
Note that the serviceId attribute in @feignClient is deprecated.
You didn't need to configure the name attribute to use urls in @feignClient before, now you must.
You can use placeholders on the URL and name properties of @FeignClient
@FeignClient(name = "${feign.name}", url = "${feign.url}")
public interface StoreClient {
//..
}
Copy the code
Spring Cloud provides some default classes for Feign
Decoder
feignDecoder:ResponseEntityDecoder
(which wraps aSpringDecoder
)Encoder
feignEncoder:SpringEncoder
Logger
feignLogger:Slf4jLogger
Contract
feignContract:SpringMvcContract
Feign.Builder
feignBuilder:HystrixFeign.Builder
Client
FeignClient: If the Ribbon is enabledLoadBalancerFeignClient
If not enabled, use the default.
The following classes are not provided by default, but will be used when creating the client
Logger.Level
Retryer
ErrorDecoder
Request.Options
Collection<RequestInterceptor>
SetterFactory
As in the previous demo, create a class and use @feignClient to configure its configuration (such as this FooConfiguration), Example
@Configuration public class FooConfiguration { @Bean public Contract feignContract() { return new feign.Contract.Default(); } @Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor() { return new BasicAuthRequestInterceptor("user", "password"); }}Copy the code
The above configuration replaces SpringMvcContract with feign.contract.default and adds an interceptor. You can also configure @feignClient using a configuration file as follows:
application.yml
eign:
client:
config:
feignName:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
errorDecoder: com.example.SimpleErrorDecoder
retryer: com.example.SimpleRetryer
requestInterceptors:
- com.example.FooRequestInterceptor
- com.example.BarRequestInterceptor
decode404: false
encoder: com.example.SimpleEncoder
decoder: com.example.SimpleDecoder
contract: com.example.SimpleContract
Copy the code
Of course, this configuration class can also be placed in the @enableFeignClients property, but if it is configured that way, all clients are in effect. If you want to configure all @feignClients, you can use the default feign name as follows:
application.yml
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: basic
Copy the code
If we create a configuration file as well as a configuration class, the configuration file has the highest priority and will override the properties of the configuration class. You can change this feature with feign.client.default-to-properties=false.
If you need to use the ThreadLocal binding parameter, you need to set Hystrix Isolation to SEMAPHORE
# To disable Hystrix in Feign
feign:
hystrix:
enabled: false
# To set thread isolation to SEMAPHORE
hystrix:
command:
default:
execution:
isolation:
strategy: SEMAPHORE
Copy the code
Create Feign client manually
In some cases the above configuration does not work for your client, then use the Feign Builder API. To manually create a client. You can use different interceptors when you create them.
@Import(FeignClientsConfiguration.class) class FooController { private FooClient fooClient; private FooClient adminClient; @Autowired public FooController(Decoder decoder, Encoder encoder, Client client, Contract contract) { this.fooClient = Feign.builder().client(client) .encoder(encoder) .decoder(decoder) .contract(contract) .requestInterceptor(new BasicAuthRequestInterceptor("user", "user")) .target(FooClient.class, "http://PROD-SVC"); this.adminClient = Feign.builder().client(client) .encoder(encoder) .decoder(decoder) .contract(contract) .requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin")) .target(FooClient.class, "http://PROD-SVC"); }}Copy the code
FeignClientsConfiguration cloud is the default configuration, the PROD – SVC is the service name. Contract uses the injected default.
Feign Hystrix Fallbacks
Concept of demotion: When code execution fails or a demotion policy is enabled, a fallback attribute can be set at @feignClient to implement this demotion policy.
@FeignClient(name = "hello", fallback = HystrixClientFallback.class) protected interface HystrixClient { @RequestMapping(method = RequestMethod.GET, value = "/hello") Hello iFailSometimes(); } static class HystrixClientFallback implements HystrixClient { @Override public Hello iFailSometimes() { return new Hello("fallback"); }}Copy the code
If you want to know the reason for the downgrade, configure the fallbackFactory property at @feignClient
FeignClient(name = "hello", fallbackFactory = HystrixClientFallbackFactory.class) protected interface HystrixClient { @RequestMapping(method = RequestMethod.GET, value = "/hello") Hello iFailSometimes(); } @Component static class HystrixClientFallbackFactory implements FallbackFactory<HystrixClient> { @Override public HystrixClient create(Throwable cause) { return new HystrixClient() { @Override public Hello iFailSometimes() { return new Hello("fallback; reason was: " + cause.getMessage()); }}; }}Copy the code
The demo above briefly explains how to implement demotion. But now downgraded strategy does not support method to return com.net flix. Hystrix. HystrixCommand and rx. Observables.
Feign and @primary
When using the degrade policy in Feign Hystrix, if an instance of the same type is in ApplicationContext. An error is reported when using @autowired injection and the @primary annotation must be used. To run properly, Spring Cloud annotates all Feign instances with the @primary annotation. There are cases where this can be problematic, so there is a way to turn it off by setting the @feignClient property primary to false.
FeignClient(name = "hello", primary = false)
public interface HelloClient {
// methods here
}
Copy the code
Feign Request/Response compression
Can open the request/response GZIP compression function, configuration properties for feign.com pression. Request. Enabled = true feign.com pression. Response. Enabled = true
There are also several web server configuration feign.com pression. Request, enabled = true feign.compression.request.mime-types=text/xml,application/xml,application/json feign.compression.request.min-request-size=2048
Eight, Feign logging
You can use the fully qualified class called Feing Client to create a recorder, recorder level DEBUG logging. Level. Project. User. UserClient: can the DEBUG configuration Logger. The level to set up the how to print log
BASIC records only the request method and URL, the response status code and the execution time HEADERS, and records BASIC information and the request and response HEADERS. FULL, a header file that records requests and responses, body, and metadata
@Configuration public class FooConfiguration { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; }}Copy the code