Spring Cloud Feign basis

Finchley.SR2

## First, what is Feign

feign web client is a declarative, you can use it in the comments to create an interface, it also supports custom codecs. Spring Cloud integrates Ribbon and Eureka provides clients with a load balancing policy. There are two main Feing Notes: (@EnableFeignClients for opening feign function, @ FeignClient used to define feign Interface).

## Second, the introduction of Feign

1, increased reliance

 <dependency>
	<groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
 </dependency>
复制代码

2、Example spring boot app

@SpringBootApplication
@EnableFeignClients
public class Application {

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

}
复制代码

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);
}
复制代码

In this @FeignClient annotation ( "stores") argument is a unique name (in fact, this is the general service name) for creating Ribbon load balancer. It can also be used on its annotation url parameters (parameter is the absolute path to find, such as www.xxx.com). . This Ribbon) This Ribbon client will find the physical address in accordance with ( "stores"), if it is used Eureka will find services in their registry, if not used can also configure an external list.

## Third, the default properties covering Feign

feign components as long as @FeignClient statement is a client, we can create our custom configuration items by using FeignClientsConfiguration, for example feign.Decoder, A  feign.Encoder, A and  feign.Contract.      Example

@FeignClient(name = "stores", configuration = FooConfiguration.class)
public interface StoreClient {
   //..
}
复制代码

In this demo client by the combination of the two and FooConfiguration FeignClientsConfiguration formed (disposed behind the override earlier)

FooConfiguration @Configuration not need this type of comment. If you need to add this to exclude when using @ComponentScan scan. Otherwise, this stuff will become feign.Decoderfeign.Encoderfeign.Contract 的默认配置了。

@FeignClient  中 serviceId 属性已经废弃了,请注意。

在以前@FeignClient 中使用url时不需要配置name属性,现在这版本必须配置。

A placeholder on @FeignClient the url attribute and name

@FeignClient(name = "${feign.name}", url = "${feign.url}")
public interface StoreClient {
   //..
}
复制代码

Spring Cloud provides several default class for Feign

  • Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecoder)
  • Encoder feignEncoder: SpringEncoder
  • Logger feignLogger: Slf4jLogger
  • Contract feignContract: SpringMvcContract
  • Feign.Builder feignBuilder: HystrixFeign.Builder
  • Client feignClient: If the Ribbon is turned on  LoadBalancerFeignClient, do not open, then you use the default.

The following class is not available by default, but in time will create a client to find the load, use some words

  • Logger.Level
  • Retryer
  • ErrorDecoder
  • Request.Options
  • Collection<RequestInterceptor>
  • SetterFactory

Just like the top of the demo, create a class using @FeignClient configure its configuration (such as is 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");
    }
}
复制代码

The above configuration is to replace SpringMvcContract feign.Contract.Default, and adds an interceptor. Of course, also possible to use a profile configured @FeignClient 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
复制代码

Of course, this configuration class can be placed inside @EnableFeignClients property, but such a configuration is so, then the client will take effect. If you want to configure all @FeignClient, you can use the default name feign default as follows:

application.yml

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: basic
复制代码

If we create a configuration file that is created and configured class, and that the highest priority of the configuration file will overwrite the configuration attributes of the class. May be used feign.client.default-to-properties = false to change this characteristic.

If you need to use ThreadLocal binding parameters, you need to set Hystrix isolation as SEMAPHORE

# To disable Hystrix in Feign
feign:
  hystrix:
    enabled: false

# To set thread isolation to SEMAPHORE
hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: SEMAPHORE
复制代码

## Fourth, manually create Feign client

In some cases the above configuration does not meet your client, you would need to use Feign Builder API . Manually create a client. When you create can use different interceptors.

@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");
    }
}
复制代码

FeignClientsConfiguration cloud is the default configuration class, PROD-SVC is the service name. Contract is injected with a default.

## five, Feign Hystrix Fallbacks (downgrade)

Downgrade concept: When code execution failure or downgrade policy is turned on, you can set a fallback property demotion to achieve this strategy @FeignClient.

@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");
    }
}
复制代码

If you want to know the reason for the downgrade, you configure fallbackFactory property in @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());
			}
		};
	}
}
复制代码

Simply put, the above demo at how to achieve a downgrade. But the downgrade policies do not support the method return com.netflix.hystrix.HystrixCommand and rx.Observable 的情况。

## six, Feign and @Primary

When downscaling strategy Feign Hystrix, if the instance of the same type ApplicationContext. @Autowired will error when using injection must be used @Primary comment. For normal operation, Spring Cloud to all Feign instances are marked @Primary comment. But this will be a problem in some cases, provide a way for all closed, you can @FeignClient primary attribute is set to false.

FeignClient(name = "hello", primary = false)
public interface HelloClient {
	// methods here
}
复制代码

## seven, Feign request / response compression can be turned request / response GZIP compression function, configure the properties on the list feign.compression.request.enabled = true feign.compression.response.enabled = true

还有几个web server的配置 feign.compression.request.enabled=true feign.compression.request.mime-types=text/xml,application/xml,application/json feign.compression.request.min-request-size=2048

## eight, Feign logging can use the fully qualified class name is Feing Client create a logger, logger level DEBUG logging.level.project.user.UserClient: DEBUG can be configured to set how the print log Logger.Level

NONE, no printing (DEFAULT). BASIC, only the recording method and the URL request and response status code and execution time HEADERS, record basic information and the request and response headers. Header FULL, record requests and responses, text and metadata

@Configuration
public class FooConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}
复制代码

Reproduced in: https: //juejin.im/post/5d0467986fb9a07eb67d8d56

Guess you like

Origin blog.csdn.net/weixin_33766805/article/details/93176211
Recommended