Feign是一个声明式的Web服务客户端。这使得Web服务客户端的写入更加方便
要使用Feign创建一个界面并对其进行注释。它具有可插拔注释支持,包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。Spring
Cloud添加了对Spring MVC注释的支持,并在Spring
Web中使用默认使用的HttpMessageConverters。Spring
Cloud集成Ribbon和Eureka以在使用Feign时提供负载均衡的http客户端。
要在您的项目中包含Feign,请使用组org.springframework.cloud
和工件IDspring-cloud-starter-feign
的启动器。有关 使用当前的Spring Cloud发布列表设置构建系统的详细信息,请参阅Spring Cloud项目页面
示例Spring Boot应用程序
@Configuration @ComponentScan @EnableAutoConfiguration @EnableEurekaClient @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); }
在@FeignClient
注释中,String值(以上“存储”)是一个任意的客户端名称,用于创建Ribbon负载平衡器。您还可以使用url属性(绝对值或只是主机名)指定URL。应用程序上下文中的bean的名称是该接口的完全限定名称。要指定自己的别名值,您可以使用@FeignClient
注释的qualifier
值。
以上的Ribbon客户端将要发现“商店”服务的物理地址。如果您的应用程序是Eureka客户端,那么它将解决Eureka服务注册表中的服务。如果您不想使用Eureka,您可以简单地配置外部配置中的服务器列表
Spring Cloud的Feign
支持中的一个中心概念就是命名的客户端。每个假装客户端是组合的组合的一部分,它们一起工作以按需联系远程服务器,并且该集合具有您将其作为应用程序开发人员使用@FeignClient
注释的名称。Spring Cloud使用FeignClientsConfiguration
为每个命名的客户端根据需要创建一个新的集合ApplicationContext
。这包含(其中包括) feign.Decoder
,feign.Encoder
和feign.Contract
。
Spring Cloud可以通过使用@FeignClient
声明其他配置(位于FeignClientsConfiguration
之上)来完全控制假客户端。例:
@FeignClient(name = "stores", configuration = FooConfiguration.class) public interface StoreClient { //.. }
在这种情况下,客户端由FeignClientsConfiguration
中的组件与FooConfiguration
中的任何组件组成(后者将覆盖前者)。
FooConfiguration
不需要使用@Configuration
注释。但是,如果是,则请注意将其从任何@ComponentScan
中排除,否则将包含此配置,因为它将成为feign.Decoder
,feign.Encoder
,feign.Contract
等的默认来源,指定时。这可以通过将其放置在任何@ComponentScan
或@SpringBootApplication
的单独的不重叠的包中,或者可以在@ComponentScan
中明确排除。
serviceId属性现在已被弃用,有利于name属性。
以前,使用url属性,不需要name属性。现在需要使用name。
name和url属性支持占位符。
@FeignClient(name = "${feign.name}", url = "${feign.url}") public interface StoreClient { //.. }
application.yml
# To disable Hystrix in Feign feign: hystrix: enabled: false # To set thread isolation to SEMAPHORE hystrix: command: default: execution: isolation: strategy: SEMAPHORE
Hystrix
支持回退的概念:当电路打开或出现错误时执行的默认代码路径。要为给定的@FeignClient
启用回退,请将fallback
属性设置为实现回退的类名。
@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 HystrixClientWithFallBackFactory() { @Override public Hello iFailSometimes() { return new Hello("fallback; reason was: " + cause.getMessage()); } }; } }
在Feign中执行回退以及如何执行Hystrix回退是有限制的。当前返回com.netflix.hystrix.HystrixCommand和rx.Observable的方法目前不支持回退。
您可以考虑启用针对您的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日志记录仅响应DEBUG级别。
application.yml
logging.level.project.user.UserClient: DEBUG
您可以为每个客户端配置的Logger.Level
对象告诉Feign记录多少。选择是:
NONE,无记录(DEFAULT)。
BASIC,只记录请求方法和URL以及响应状态代码和执行时间。
HEADERS,记录基本信息以及请求和响应头。
FULL,记录请求和响应的头文件,正文和元数据。
例如,以下将Logger.Level
设置为FULL
:
@Configuration public class FooConfiguration { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }