Spring Cloud Netflix子模块综合整理-Feign

- 日理万妓 2022-05-19 05:15 237阅读 0赞

声明性REST客户端:Feign

Feign是一个声明性的Web服务客户端。 它使编写Web服务客户端变得更容易。 要使用Feign需要创建一个接口并添加相应的注释。 它具有可插入的注释支持,包括Feign注释和JAX-RS注释。 Feign还支持可插拔编码器和解码器。 Spring Cloud增加了对Spring MVC注释的支持,并使用了Spring Web中默认使用的相同HttpMessageConverters【重点】。Spring Cloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。

如何添加Feign

  1. <!--引入feign -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-feign</artifactId>
  5. </dependency>

应用实例

springboot启动类

  1. @Configuration
  2. @ComponentScan
  3. @EnableAutoConfiguration
  4. @EnableEurekaClient
  5. //启动feign
  6. @EnableFeignClients
  7. public class Application {
  8. public static void main(String[] args) {
  9. SpringApplication.run(Application.class, args);
  10. }
  11. }

调用接口

  1. //stores 被调用方无名名
  2. @FeignClient("stores")
  3. public interface StoreClient {
  4. //添加调用路径,具体需要调用那个方法
  5. @RequestMapping(method = RequestMethod.GET, value = "/stores")
  6. List<Store> getStores();
  7. @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
  8. Store update(@PathVariable("storeId") Long storeId, Store store);
  9. }

在上面@FeignClient注解中,(“stores”)是一个任意客户端名称,用于创建Ribbon负载均衡器, 您还可以使用url属性指定URL(绝对值或仅指定主机名)。 应用程序上下文中bean的名称是接口的完全限定名称。 要指定自己的别名值,可以使用限定符@FeignClient注释的值。

上面的Ribbon客户端将要发现“stores”服务的物理地址。 如果您的应用程序是Eureka客户端,那么它将解析Eureka服务注册表中的服务(从注册中心获取具体的”stores”服务调用地址)。 如果您不想使用Eureka,则只需在外部配置中配置服务器列表即可

覆盖默认的Feign配置

Spring Cloud的Feign支持的核心概念是指定客户端的概念。 每个feign客户端都是一组组件的一部分,这些组件一起工作以按需联系远程服务器,并且该集合具有一个名称,您可以使用@FeignClient注释将其作为应用程序开发人员提供。 Spring Cloud根据需要为每个命名客户端创建一个新的集合作为ApplicationContext FeignClientsConfiguration。 这包含(除其他外)feign.Decoder,feign.Encoder和feign.Contract。【Feign的默认配置是FeignClientsConfiguration,该类定义了Feign默认使用的编码器、解码器、所有使用的契约】

Spring Cloud允许您通过使用@FeignClient的configuration属性自定义Feign的配置,自定义的优先级会比默认的FeignClientsConfiguration优先极高。

例如:

  1. //FooConfiguration 自定义配置
  2. @FeignClient(name = "stores", configuration = FooConfiguration.class)
  3. public interface StoreClient {
  4. //..
  5. }

注意:

FooConfiguration不需要使用@Configuration注释。 但是,如果是,则注意将其从任何包含此配置的@ComponentScan中排除,因为该配置会被所有@FeignClient共享。 这可以通过将它放在来自任何@ComponentScan或@SpringBootApplication的单独的非重叠包中来避免,或者可以在@ComponentScan中明确排除它

在@FeignClient中推荐使用name属性,serviceId属性已经过期不推荐了。

以前可能使用url属性,写具体调用服务的物理地址,现在只需写name属性填写具体的服务名称,将会自动解析。

70

@FeignClient注解中还支持name和url属性值得占位符。

  1. @FeignClient(name = "${feign.name}", url = "${feign.url}")
  2. public interface StoreClient {
  3. //..
  4. }

spring Cloud Netflix默认为feign(BeanType beanName:ClassName)提供以下bean:

  • Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecoder ) //相应编码
  • Encoder feignEncoder: SpringEncoder //采用的编码
  • Logger feignLogger: Slf4jLogger //采用的日志
  • Contract feignContract: SpringMvcContract //默认请求调用方式采用springmvc注解方式 即就是@RequestMapping
  • Feign.Builder feignBuilder: HystrixFeign.Builder
  • Client feignClient: if Ribbon is enabled it is a LoadBalancerFeignClient , otherwise the default feign client is used //如果没有禁用ribbon,服务调用将通过负载均衡调用

创建其中一种类型的bean并将其放在@FeignClient配置中(例如下面的FooConfiguration)允许您覆盖默认。

  1. @Configuration
  2. public class FooConfiguration {
  3. @Bean
  4. public Contract feignContract() {
  5. return new feign.Contract.Default();
  6. }
  7. @Bean
  8. public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
  9. return new BasicAuthRequestInterceptor("user", "password");
  10. }
  11. }

上面讲使用feign原生的默认契约去掉springmvc,这样就可以使用feign自带的注解了。而且配置基于用户认证,只有通过认证才能调用。

@FeignClient相关配置还可通过配置文件配置

application.yml
70 1

如果您更喜欢使用配置属性来配置所有@FeignClient,则可以使用默认的Feign name创建配置属性。

70 2

如果同时创建@Configuration bean和属性配置文件,则配置属性优先级高。 它将覆盖@Configuration值。 但是,如果要将优先级更改为@Configuration,则可以将feign.client.default-to-properties更改为false。

注意:

如果你需要使用ThreadLocal绑定变量,需要进行如下设置。

在feign调用中禁用断路器和膝盖修改线程隔离策略。

70 3

在feign用使用Hystrix

如果Hystrix在类路径上并且feign.hystrix.enabled = true,则Feign将使用断路器包装所有方法(这是一个全局的配置).

如果不想设置全局的关闭hystrix,而只是针对某个服务关闭Hystrix需要如下配置:

  1. @Configuration
  2. public class FooConfiguration {
  3. @Bean
  4. @Scope("prototype")
  5. public Feign.Builder feignBuilder() {
  6. return Feign.builder();
  7. }
  8. }

Feign服务降级配置

Hystrix支持回退的概念:在电路打开或出现错误时执行的默认代码路径。 要为给定的@FeignClient启用回退,请将fallback属性设置为实现回退的类名。 您还需要将实现声明为Spring bean。

实例代码:

  1. @FeignClient(name = "hello", fallback = HystrixClientFallback.class)
  2. //定义服务调用接口
  3. protected interface HystrixClient {
  4. @RequestMapping(method = RequestMethod.GET, value = "/hello")
  5. Hello iFailSometimes();
  6. }
  7. //服务降级类需要实现服务调用接口
  8. static class HystrixClientFallback implements HystrixClient {
  9. @Override
  10. public Hello iFailSometimes() {
  11. return new Hello("fallback");
  12. }
  13. }

如果需要访问导致回退触发器的原因,可以使用@FeignClient中的fallbackFactory属性。

  1. @FeignClient(name = "hello", fallbackFactory = HystrixClientFallbackFactory.class)
  2. protected interface HystrixClient {
  3. @RequestMapping(method = RequestMethod.GET, value = "/hello")
  4. Hello iFailSometimes();
  5. }
  6. @Component
  7. static class HystrixClientFallbackFactory implements FallbackFactory<HystrixClient> {
  8. @Override
  9. public HystrixClient create(Throwable cause) {
  10. return new HystrixClient() {
  11. @Override
  12. public Hello iFailSometimes() {
  13. return new Hello("fallback; reason was: " + cause.getMessage());
  14. }
  15. };
  16. }
  17. }

Feign and @Primary

在Feign使用Hystrix做服务降级时,ApplicationContext中有多个相同类型的bean。 这将导致@Autowired无法工作,因为没有一个bean或一个标记为primary的bean。 为了解决这个问题,Spring Cloud Netflix将所有Feign实例标记为@Primary,因此Spring Framework将知道要注入哪个bean。 在某些情况下,这可能并不理想。 要关闭此行为,请将@FeignClient的主要属性设置为false。

  1. @FeignClient(name = "hello", primary = false)
  2. public interface HelloClient {
  3. // methods here
  4. }

Feign对继承的支持

Feign支持单接口继承,这样可以将常用的进行接口封装。

列如:

UserService.java

  1. public interface UserService {
  2. @RequestMapping(method = RequestMethod.GET, value ="/users/{id}")
  3. User getUser(@PathVariable("id") long id);
  4. }

UserResource.java

  1. @RestController
  2. public class UserResource implements UserService {
  3. }

UserClient.java

  1. package project.user;
  2. @FeignClient("users")
  3. public interface UserClient extends UserService {
  4. }

通常不建议在服务器和客户端之间共享接口因为增强了耦合,并且实际上也不能以其当前形式使用Spring MVC(方法参数映射不会被继承)

Feign请求和响应压缩

您可以考虑为您的Feign请求启用请求或响应GZIP压缩。 您可以通过启用以下属性之一来执行此操作:

  1. feign.compression.request.enabled=true
  2. feign.compression.response.enabled=true

Feign请求压缩为您提供类似于您为Web服务器设置的设置:

  1. feign.compression.request.enabled=true
  2. feign.compression.request.mime-types=text/xml,application/xml,application/json
  3. feign.compression.request.min-request-size=2048

通过这些属性,您可以选择压缩介质类型和最小请求阈值长度

Feign 日志

为每个创建的Feign客户端创建一个日志记录器。 默认情况下,日志记录器的名称是用于创建Feign客户端的接口的完整类名。 Feign日志记录仅响应DEBUG级别。

application.yml.

  1. logging.level.project.user.UserClient: DEBUG

您可以为每个客户端配置的Logger.Level对象告诉Feign记录日志级别,支持四种日志级别:

  • NONE , No logging (DEFAULT).// 默认不打印日志
  • BASIC , Log only the request method and URL and the response status code and execution time.//仅记录请求方法和URL以及响应状态代码和执行时间
  • HEADERS , Log the basic information along with request and response headers.//记录基本信息以及请求和响应标头
  • FULL , Log the headers, body, and metadata for both requests and responses.//记录请求和响应的标题,正文和元数据。

例如配置打印所有日志,设置Logger.Level 为FULL

  1. @Configuration
  2. public class FooConfiguration {
  3. @Bean
  4. Logger.Level feignLoggerLevel() {
  5. return Logger.Level.FULL;
  6. }
  7. }

微信公众号

  1. ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25pdWdhbmcwOTIw_size_16_color_FFFFFF_t_70][]

发表评论

表情:
评论列表 (有 0 条评论,237人围观)

还没有评论,来说两句吧...

相关阅读