Feign 声明性REST客户端
- Feign是一个声明式的WEB服务客户端。
- Feign具有可插入注释支持:
- Feign注释
- JAX-RS注释
- 可插拔编码器和解码器
- SpringCloud 集成Ribbon和Eureka以在使用Feign时提供负载均衡的http客户端
引入Feign
-
开启Feign客户端注解:@EnableFeignClients
-
开启Feign客户端
-
@Configuration @ComponentScan @EnableAutoConfiguration @EnableEurekaClient @EnableFeignClients public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
-
-
远程调用方式:
-
@FeignClient("ORDER-SERVER") public interface StoreClient { @RequestMapping(method = RequestMethod.GET, value = "/orders") List<Order> getOrders(); @RequestMapping(method = RequestMethod.POST, value = "/orders/{orderId}", consumes = "application/json") Store update(@PathVariable("orderId") String orderId, Order order); }
-
-
使用Feign core提供的@RequestLine 注解
-
@RequestLine("GET /api/documents/{contentType}") @Headers("Accept {contentType}") String getDocumentByType(@Param("contentType") String type);
- 注意:
- 启动报错: Method getLinksForTrack not annotated with HTTP method type (ex. GET, POST)
- 原因: feign 默认使用的是spring mvc 注解(就是RequestMapping 之类的), 所以需要配置feign的Configuration
- 解决:
-
@Configuration public class MyFeignConfiguration { @Bean public Contract feignConfiguration(){ return new feign.Contract.Default(); } }
- 注意:网上说如果命名为FeignConfiguration可能会导致启动失败,原因是springcloud有一个FeignConfiguration类
- 默认情况下,@RequestLine和@QueryMap模板不编码斜杠/字符。要更改此行为,请将@RequestLine上的decodeSlash属性设置为false
-
-
Feign 接口注释
-
Annotation Interface Target Usage @RequestLine
Method 为请求定义HttpMethod和UriTemplate。表达式,用花括号{表达式}包装的值使用它们对应的@Param带注释的参数进行解析。 @Param
Parameter 根据名称定义模板变量,其值将用于解析相应的模板“表达式”。 @Headers
Method, Type 定义了一个“HeaderTemplate”;“UriTemplate”的变体。它使用“@Param”注释值来解析相应的“表达式”。当用于“类型”时,模板将应用于每个请求。当在“方法”上使用时,模板将只应用于带注释的方法。 @QueryMap
Parameter 定义名称-值对(或POJO)的“映射”,以展开为查询字符串。 @HeaderMap
Parameter 定义名称-值对的“映射”,以展开为“Http Header” @Body
Method 定义一个“模板”,类似于“UriTemplate”和“HeaderTemplate”,它使用“@Param”注释值来解析相应的“表达式”
-
配置Feign
-
Spring Cloud 根据需要,可以使用FeignClientConfiguration为每个已命名的客户端创建一个新的ApplicationContext。
- 其中包含feign.Decoder,feign.Encoder 和feign.Contract
-
具体配置
- @FeignClient(name=“ORDER-SERVER”,configuration = FeignConfiguration.class)
-
注意:
- FeignConfiguration不需要使用@Configuration注释。
- 如果使用,则需要将其从任何@ComponentScan中排除
- 因为feign.Decoder,feign.Encoder,feign.Contract的默认来源
- 指定时。这可以通过将其放置在任何@ComponentScan或@SpringBootApplication的单独的不重叠的包中,或者可以在@ComponentScan中明确排除。
-
支持占位符:
- @FeignClient(name = “ f e i g n . n a m e " , u r l = " {feign.name}", url = " feign.name",url="{feign.url}”)
-
Decoder: feignDecoder: ResponseEntityDecoder(其中包含SpringDecoder)
-
Encoder:feignEncoder:SpringEncoder
-
Logger:feignLogger: Slf4jLogger
-
Contract: feignContract: SpringMvcContract
-
Feign.Builder: feignBuilder: HystrixFeign.Builder
-
Client: feignClient: 如果Ribbon启用,则为LoadBalancerFeignClient,否则将使用默认的feign客户端
-
feign.okhttp.enabled: true或feign.httpclient.enabled: true
- 将他们放在类路径上来使用OkHttpClient和ApacheHttpClient feign客户端
-
代码示例
-
@Configuration public class FeignConfiguration { @Bean public Contract feignContract() { return new feign.Contract.Default(); } @Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor() { return new BasicAuthRequestInterceptor("user", "password"); } }
- 这将SpringMvcContract替换为feign.Contract.Default,并将RequestInterceptor添加到RequestInterceptor的集合中。
-
Feign Hystrix
- 开启熔断器:
- feign.hystrix.enabled: true
- Feign Hystrix Fallbacks
- Hystrix支持回退的概念:当执行断路或传错误时执行的默认代码路径
-
@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("当前并发太高,请稍后再试!"); } }
- 如果需要方位导致回退的触发原因,可以使用@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 和 @Primary
-
当使用Feign与Hystrix回退时,在同一类型的ApplicationContext中有多个bean。
这将导致@Autowired不起作用,因为没有一个bean,或者标记为主。要解决这个问题,
Spring Cloud Netflix将所有Feign实例标记为@Primary,所以Spring Framework
将知道要注入哪个bean。在某些情况下,这可能是不可取的。要关闭此行为,
将@FeignClient的primary属性设置为false。
Ribbon 配置
- 常用application.yml配置
-
# 设置连接超时时间 ribbon.ConnectTimeout=600 # 设置读取超时时间 ribbon.ReadTimeout=6000 # 对所有操作请求都进行重试 ribbon.OkToRetryOnAllOperations=true # 切换实例的重试次数 ribbon.MaxAutoRetriesNextServer=2 # 对当前实例的重试次数 ribbon.MaxAutoRetries=1
-