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

 声明性REST客户端:Feign

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

如何添加Feign

<!--引入feign -->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

应用实例

  springboot启动类

@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableEurekaClient
//启动feign
@EnableFeignClients
public class Application {

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

}

调用接口

//stores 被调用方无名名
@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);
}

在上面@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优先极高。

例如:

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

注意:

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

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

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

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

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

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)允许您覆盖默认。

@Configuration
public class FooConfiguration {
  @Bean
  public Contract feignContract() {
   return new feign.Contract.Default();
  }
  @Bean
 public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
   return new BasicAuthRequestInterceptor("user", "password");
  }
}

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

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

application.yml

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

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

注意:

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

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

在feign用使用Hystrix

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

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

 @Configuration
public class FooConfiguration {
  @Bean
  @Scope("prototype")
 public Feign.Builder feignBuilder() {
  return Feign.builder();
 }
}

Feign服务降级配置

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

实例代码:

@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");
    }
}

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

@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());
			}
		};
	}
}

Feign and @Primary

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

@FeignClient(name = "hello", primary = false)
public interface HelloClient {
 // methods here
}

Feign对继承的支持

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

列如:

UserService.java

public interface UserService {

    @RequestMapping(method = RequestMethod.GET, value ="/users/{id}")
    User getUser(@PathVariable("id") long id);
}

UserResource.java

@RestController
public class UserResource implements UserService {

}

UserClient.java

package project.user;

@FeignClient("users")
public interface UserClient extends UserService {

}

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

Feign请求和响应压缩

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

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

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

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

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

Feign 日志

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

application.yml.

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

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

猜你喜欢

转载自blog.csdn.net/niugang0920/article/details/81137329
今日推荐