Wechat search [small two said code] attention, regular release of technical articles, welcome to pay attention to

Feign

Me Feign

  • The version of cloud in this paper is Greenwich.RELEASE
  • Feign is a piece of shit. ^_^This is not a simple thingWhat is it? According to the official website:
    • Client component that provides calls between client and server.
    • Can be achieved by@ConfigurationAnnotations or configuration files to load the configuration
    • Support for SpringMVC annotations and use HttpMessageConverters as message converters, such as @getMapping
    • There are two heavy weights: the Ribbon for load and retry; Hystrix to downgrade and fuse

  • FeignClient uses JDK dynamic proxies to build Client objects and encapsulate methods and parameters into the objectsMap<Method, MethodHandler>, which is called using the method name and arguments

Service remote invocation mode

  • Method 1:LoadBalanceClientThe way ofhttp://ip:port/path(LoadBalanceClient+RestTemplate)
@Autowired
private LoadBalancerClient loadBalancerClient;
@Resource
private RestTemplate restTemplate;
// Call this example
restTemplate.getForObject(http:ip+port+path,xxx);
Copy the code
  • Method 2:Ribbon: http://servicaName/path (RestTemplate + Ribbon)
/ / into the Bean
@LoadBalanced
@Bean
public RestTemplate restTemplate(a) {
    return new RestTemplate();
}
// Inject directly into the class
@Resource
private RestTemplate restTemplate;

/ / reference
// Call this example
restTemplate.getForObject(serviceId+path,xxx);
Copy the code
  • Method 3: This chapter’s killer **Feign** Interface calls via the integration Ribbon, proxy integration, @feignClient (“service-name”)
// Inject the @feignClient annotated orderService directly into the class
@Autowired 
private OrderService orderService;
Copy the code
  • The first two methods are cumbersome, requiring the injection of objects and the concatenation of HTTP during the call, while the third Feign method is directly through the injection of objects, which is quite convenient to use, like using a local Service, so it is mainly explained

Feign development

Introduction to use
  • ① Introduce package, ② add startup class@EnableFeignClients(3) configuration@FeigntClientFor details, please refer to the official website:spring-cloud-starter-openfeign
Use advanced
Custom configuration (logging, interceptors, encodings, and decoding)
  • Log bean configuration mode
    • Add configuration to FeignClient@FeignClient(name = "storage", fallback = StorageFallback.class, configuration = FeignConfiguration.class)
    • Override default configuration 1:FeignConfigurationConfigure the bean to override the default Feign configuration when the class is not configured@ConfigurationAnnotations to avoid overwriting other Feign defaults
// Do not configure @configuration annotations
@Slf4j
public class FeignConfiguration {
	/ / configuration Bean
	@Bean
	public Logger.Level level(a) {
	    returnLogger.Level.FULL; }}// Notice If logs do not take effect, set the log level of the client to DEBUG
logging:
  level:
    com.feign.XXXClient: debug
Copy the code
  • Mode 2: Configuration file (YML) Mode
feign:
  client:
    config:
      default: loggerLevel: full requestInterceptors: # can be used to transfer the token, tracking id need to relay the information in the header - com. Frank. The interceptor. StorageFeignInterceptorCopy the code
  • If the Bean configuration mode and the configuration file exist together, the configuration file mode takes precedence
  • The configuration of interceptors, encoders, and decoders also supports the above two methods
Dizzying time configuration
  • First to find a limit algorithm!! Believe a lot: The hero is stumped, so how to calculate the maximum? Dong dong dong… No more suspense. Maximum time =(ReadTimeout? +ConnectTimeout) * (MaxAutoRetries + 1) * (MaxAutoRetriesNextServer + 1)(? 0 times or 1 times), is not much simpler than the limit algorithm of data! High number of various limit method dazzling, long back to the teacher, ha ha! Note:The ribbon defaults to one retry for a machine
# # ribbon timeout each machine maximum retries, default is once, that is to say if without configuration request timeout will retry a storage. Ribbon. MaxAutoRetries =2# and try again a few machine storage. Ribbon. MaxAutoRetriesNextServer =2# connection timeout, connection timeout can be set smaller storage. Ribbon. The ConnectTimeout =1000# business processing timeout storage. Ribbon. ReadTimeout =2000Retries are performed on all HTTP methodsfalse, if the production environment is configured with #trueYou need to set up idempotent storage. Ribbon. OkToRetryOnAllOperations =true
Copy the code
  • The configuration of the priority level is lower than fegin. Client. Config. Default. XxxTimeout time allocation, this configuration will cover ribbon time configuration, the ribbon configuration parameters of time and retry all don’t take effect
Feign: client: config: # Specifies your own feign name, defaultdefaultEffect on all Feigndefault:
        connectTimeout: 5000
        readTimeout: 5000
Copy the code
  • If the timeout period is set properly, hystix=connectTimeout+readTimeout is recommended and the validity time priority is feign > Hystrix > ribbon > HTTP
Downgrade & circuit breaker
  • The degraded configuration needs to be implemented in the client
  • Open the configuration
feign:
  hystrix:
    enabled: trueHystrix: command: # Hystrix: command: # Hystrix: command: # Hystrix: command: # Hystrix: command: # Hystrix: command: #default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000
Copy the code
  • Degraded configuration: in@FeignClient– Added fallBack configuration class to implement client and spring context, as well as factory interface
@FeignClient(name = "storage", fallback = StorageClientFallback.class)
protected interface StorageClient{
    @GettMapping("/fallback")
    String fallback(Integer flag);
}

// The inner class does not need to add Bean context annotations, if the separate implementation needs to configure the @Component annotation
static class StorageClientFallback implements StorageClient{
    @Override
    public String fallback(Integer flag) {
        return "fallback"; }}Copy the code
  • If 20 errors occur within the default 5 seconds, the circuit breaker will open and all requests will be fuses
  • Hystrix command Configures the command

The source code to read

Feign source @enableFeignClients
  • The first instinct to load a configuration in a startup class is to initialize a component, yes, here@EnableFeignClientsThe function of Feign is to load the definition of Feign.
    • FeignClientsRegistrarClass implements theImportBeanDefinitionRegistrarInterface, which registers the Feign configuration and FeignClient definition in the method
    • Voiceover: Many components are loaded in this way, so it can also be implemented during component developmentImportBeanDefinitionRegistrarInterface to load custom components
Feign source code FeignClientFactoryBean
  • seeXXXFactoryBeanObject (Voiceover: One way to create Spring objects, and you can imagine other ways to create objects), you can guess that objects are created in the way of factory beans. When the Client needs to be loaded during Spring context initialization, the Client object is created using a FactoryBean
  • A flowchart

  • Core creation method is as follows:
public <T> T newInstance(Target<T> target) {
    Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
    // Methods and methods handle the mapping of handlers
    Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();
    List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();

    for (Method method : target.type().getMethods()) {
      if (method.getDeclaringClass() == Object.class) {
        continue;
      } else if (Util.isDefault(method)) {
        DefaultMethodHandler handler = new DefaultMethodHandler(method);
        defaultMethodHandlers.add(handler);
        methodToHandler.put(method, handler);
      } else{ methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method))); }}/ / create InvocationHandler
    InvocationHandler handler = factory.create(target, methodToHandler);
    // Create a dynamic proxy object
    T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),
        newClass<? >[] {target.type()}, handler);for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
      defaultMethodHandler.bindTo(proxy);
    }
    return proxy;
  }
Copy the code

Your praise and attention is the biggest power of my creation, any shortcomings and mistakes welcome to leave a message, wechat search attention xiao Er said code