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


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

    一、概述

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

      注意:JAX-RSJAX-WS

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

    1.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);
    }

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

        //请求不会成功,只要参数是复杂对象,即使指定了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.2、覆写Feign的默认配置

    1.2.1、概述

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

      每个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.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.3、非默认配置

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

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

    1.2.4、开发

    编写一个默认注解

    @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.5、如果请求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.6、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.3、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.4、Feign第一次启动timeout问题

      hystrix默认1秒超时

    方法一、可配置超时时间增加:

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

    方法二、关闭熔断超时

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

    方法三、关闭熔断机制

    feign.hystrix.enabled: false

    可以参看:https://github.com/Netflix/Hystrix/wiki/Configuration

    1.5、手动创建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.6、feign源码实现过程

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

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

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

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

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

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

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

  • 相关阅读:
    POM (Project Object Model)简介
    Maven 依赖管理
    Maven仓库—Nexus环境搭建及简单介绍
    Maven的几个核心概念
    maven本地仓库的配置以及如何修改默认.m2仓库位置
    Maven修改镜像仓库地址
    Maven生命周期
    Maven 和 Ant 的区别?
    Maven简介
    Maven常用命令
  • 原文地址:https://www.cnblogs.com/bjlhx/p/8870901.html
Copyright © 2020-2023  润新知