0406-服务注册与发现-客户端feign-使用、配置、日志、timeout

官方地址:https://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#spring-cloud-feignhtml

1、概述

  Feign是一个声明式Web服务客户端。它使编写Web服务客户端变得更容易。使用Feign建立一个接口并对其进行注释。它具备可插入的注释支持,包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。 Spring Cloud添加了对Spring MVC注释的支持,而且使用了Spring Web中默认使用的相同HttpMessageConverters。Spring Cloud将Ribbon和Eureka集成在一块儿,在使用Feign时提供负载均衡的http客户端。git

  注意:JAX-RSJAX-WSgithub

  源码地址:https://github.com/OpenFeign/feignspring

1.一、基础使用

1》添加pom

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

2》启动类上添加注解

@SpringBootApplication @EnableFeignClients public class ComsumerMovieFeignApplication { public static void main(String[] args) { SpringApplication.run(ComsumerMovieFeignApplication.class, args); } }

3》添加一个接口并为接口添加注解,调用用户服务

@FeignClient("microservice-provider-user") public interface UserFeignClient { // @GetMapping("/sample/{id}")
    @RequestMapping(method = RequestMethod.GET, value = "/movie/{id}") public User findById(@PathVariable("id") Long id); }

注意点:一、spring注解不能使用getMapping,需使用RequestMapping;二、@PathVariable必须添加参数;三、当服务接受参数是一个对象时候,此时默认会转化为post请求,及时接口写的是get请求【?待解决】json

//请求不会成功,只要参数是复杂对象,即便指定了GET方法,feign依然会以post方法进行发送
    @RequestMapping(method = RequestMethod.GET, value = "/get-user") public User getUser(User user);

4》程序调用

 @Autowired private UserFeignClient userFeignClient; @GetMapping("/movie/{id}") public User findById(@PathVariable Long id) { return userFeignClient.findById(id); }

执行post相似服务器

参考代码:https://github.com/bjlhx15/spring-cloud/tree/master/microservice-comsumer-movie-feign网络

1.二、覆写Feign的默认配置

1.2.一、概述

  Spring Cloud的Feign支持中的一个中心概念是指定的客户端。app

  每一个feign客户端都是总体的一部分,这些组件是一块儿工做以根据须要联系远程服务器,而且该组件具备一个名称,开发人员可使用@FeignClient批注命名。负载均衡

  Spring Cloud使用FeignClientsConfiguration建立一个新的集合,做为每一个指定客户端的ApplicationContext。这包含(除其余外)feign.Decoder,feign.Encoder和feign.Contract。框架

  经过使用@FeignClient声明额外配置(在FeignClientsConfiguration之上),Spring Cloud可以让您彻底控制客户端

示例

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

  注意事项:FooConfiguration 同RibbonConfiguration一致放包问题,参看:http://www.cnblogs.com/bjlhx/p/8859088.html

  注意事项2:之前使用url能够不用,如今必须使用name

1.2.二、默认配置

Spring Cloud Netflix默认提供如下bean for feign(BeanType beanName:ClassName):

  • Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecoder) 默认解码
  • Encoder feignEncoder: SpringEncoder 默认编码
  • Logger feignLogger: Slf4jLogger 默认日志
  • Contract feignContract: SpringMvcContract 默认契约
  • Feign.Builder feignBuilder: HystrixFeign.Builder 默认构建builder
  • Client feignClient: if Ribbon is enabled it is a LoadBalancerFeignClient, otherwise the default feign client is used.  默认client

  经过将feign.okhttp.enabled或feign.httpclient.enabled分别设置为true并将它们放在类路径中,可使用OkHttpClient和ApacheHttpClient feign客户端。当使用Apache或OkHttpClient使用OK HTTP时,能够经过提供ClosableHttpClient的bean来定制HTTP客户端。

1.2.三、非默认配置

  Spring Cloud Netflix默认状况下不提供如下bean,但仍从应用程序上下文中查找这些类型的bean以建立假客户端:

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

1.2.四、开发

编写一个默认注解

@Configuration public class Configuration1 { @Bean public Contract feignContract() { return new feign.Contract.Default(); } }

  由于原默认注解使用spring的如今这里改用feign契约,故如下调用须要使用feign的注解RequestLine等

编写客户端调用

@FeignClient(name = "microservice-provider-user", configuration = Configuration1.class) public interface UserFeignClient { @RequestLine("GET /sample/{id}") public User findById(@Param("id") Long id); }

程序使用便可。

参看代码:https://github.com/bjlhx15/spring-cloud/tree/master/microservice-comsumer-movie-feign-customizing

1.2.五、若是请求eureka的接口如

@FeignClient(name = "xxxx", url = "http://localhost:8761/", configuration = Configuration2.class) public interface FeignClient2 { @RequestMapping(value = "/eureka/apps/{serviceName}") public String findServiceInfoFromEurekaByServiceName(@PathVariable("serviceName") String serviceName); }

由于eureka设置了权限此时访问失败

需增长配置类,Configuration2增长权限校验

@Configuration public class Configuration2 { @Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor() { return new BasicAuthRequestInterceptor("user", "a123"); } }

1.2.六、Feign请求/响应压缩

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

这些属性使您能够选择压缩媒体类型和最小请求阈值长度。

 1.三、feign日志

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

application.yml. 

logging.level.project.user.UserClient: DEBUG

注level是具体类路径。可能不生效,须要配置一下配置

您能够为每一个客户端配置的Logger.Level对象告诉Feign要记录多少。选择是:

  • NONE, No logging (DEFAULT).
  • BASIC, 只记录请求方法和URL以及响应状态码和执行时间。
  • HEADERS, 记录基本信息以及请求和响应标头。
  • FULL, 为请求和响应记录标题,正文和元数据。

例如,如下操做将Logger.Level设置为FULL:

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

参看代码:https://github.com/bjlhx15/spring-cloud/tree/master/microservice-comsumer-movie-feign-customizing

1.四、Feign第一次启动timeout问题

  hystrix默认1秒超时

方法1、可配置超时时间增长:

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000

方法2、关闭熔断超时

hystrix.command.default.execution.timeout.enabled: false

方法3、关闭熔断机制

feign.hystrix.enabled: false

能够参看:https://github.com/Netflix/Hystrix/wiki/Configuration

1.五、手动建立Feign客户端

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

1.六、feign源码实现过程

一、首先经过@EnabledFeignClients注解开启FeignClient的功能。主要是启动程序时开启对@FeignClient注解的包扫描

二、根据feign的规则实现接口,并在接口上面加上@FeignClient注解

三、程序启动后,进行包扫描,扫描全部的@FeignClient的注解的类,并将这些类放入Ioc容器。

四、当接口的方法被调用时,经过JDK的代理来生成具体的RequestTemplate模板对象

五、根据RequestTemplate再生成Http请求的Request对象。

六、Request对象交给Client去处理,其中Client的网络请求框架能够是HttpURLConnetion,HTTPClient和OkHttp等

七、最后Client被封装到LoadBlanceClient类,这个类结合类Ribbon作负载均衡。 

相关文章
相关标签/搜索