• 客户端远程调用Feign


    客户端远程调用

    Feign

    什么是Feign?

    Feign是 Netflix 公司开源的声明式HTTP客户端

    Github : Feign 源码

    为什么需要Feign?

    1. 原代码可读性不高
    2. 复杂的URL难以维护(https://user-center/s?wd={userId}&rsv_spt=1&rsv_iqid=0x93bff3cd000cf3da&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=4&rsv_sug1=4&rsv_sug7=100&rsv_t=10c2risCimsUZC0RBruMerdnQRN1gRxFI%2BywuD0L3LwGGNd2dR8XE6x%2FyFOjHnR0oEi0&rsv_sug2=0&inputT=1535&rsv_sug4=1535&rsv_sug=2
    3. 难以应对需求的快速变化
    4. 编码体验和我们写JAVA差异较大

    举例重构代码

    				//替换前 
            ResponseEntity<UserDTO> userEntity = restTemplate.getForEntity(
                    "http://user-center/users/{userId}",
                    UserDTO.class, userId
            );
            UserDTO userDTO = new UserDTO();
            if (null != userEntity) {
                userDTO = userEntity.getBody();
                log.info("ShareService#findById userDTO: {}", userDTO);
            }
    
    1. 添加依赖
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
    
    1. 启动类添加注解 @EnableFeignClients
    2. 添加配置
    3. 实现对应微服务的client
    /**
     * IUserCenterFeignClient for 定义 user-center feign client
     *
     * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
     * @since 2019/7/15
     */
    @FeignClient(name = "user-center")
    public interface IUserCenterFeignClient {
    
        /**
         * Feign client 会将请求转换为
         * http://user-center/users/{userId}
         *
         * @param userId 用户id
         * @return 返回用户对象
         */
        @GetMapping(path = "/users/{userId}")
        public UserDTO findById(@PathVariable Long userId);
    }
    
    1. 替换后代码
            //使用 FeignClient 来替换掉RestTemplate调用
            UserDTO userDTO = this.userCenterFeignClient.findById(userId);
    

    Feign的组成

    Feign的配置方式

    Java Code

    支持的配置项

    自定义Feign日志级别
    • 级别内容

    Demo

    **Tip **: 有可能出现父子上下文重叠问题

    1. 在client添加配置
    /**
     * IUserCenterFeignClient for 定义 user-center feign client
     *
     * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
     * @since 2019/7/15
     */
    @FeignClient(name = "user-center",configuration = UserCenterFeignConfiguration.class)
    public interface IUserCenterFeignClient {
       ...
    }
    
    1. 编写java配置文件
    /**
     * UserCenterFeignConfiguration for 自定义user-center服务请求中,feign的配置信息
     * {@link @Configuration} 不能添加该注解,否则会和ribbon一样,出现上下文重叠问题,造成配置全局共享
     * 如要添加该注解,需要将该类放在主程序启动扫描不到的包下
     *
     * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>
     * @since 2019/7/15
     */
    public class UserCenterFeignConfiguration {
        @Bean
        public Logger.Level level() {
            // 配置feign 日志级别,记录请求和响应的header、body以及元数据
            return Logger.Level.FULL;
        }
    }
    
    1. 一定要在配置文件中添加该client 全路径

      logging:
        level:
         #com.sxzhongf: debug
          com.sxzhongf.sharedcenter.feignclients.IUserCenterFeignClient: debug
      
    2. 打印信息

    2019-07-15 15:06:11.650 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] <--- HTTP/1.1 200 (402ms)
    2019-07-15 15:06:11.651 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] content-type: application/json;charset=UTF-8
    2019-07-15 15:06:11.651 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] date: Mon, 15 Jul 2019 07:06:11 GMT
    2019-07-15 15:06:11.651 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] transfer-encoding: chunked
    2019-07-15 15:06:11.652 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] 
    2019-07-15 15:06:11.652 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] {"id":1,"wxId":"","wxNickname":"IsaacZhang","roles":"","avatarUrl":"aaa","createTime":"2019-07-11T06:08:18.000+0000","updateTime":"2019-07-11T06:08:18.000+0000","bonus":100}
    2019-07-15 15:06:11.652 DEBUG 20286 --- [nio-8010-exec-1] c.s.s.f.IUserCenterFeignClient           : [IUserCenterFeignClient#findById] <--- END HTTP (173-byte body)
    

    Configuration

    支持的配置项

    demo

    使用配置文件来定义log level

    #logging:
      #level:
       #com.sxzhongf: debug
        #com.sxzhongf.sharedcenter.feignclients.IUserCenterFeignClient: debug
    feign:
      client:
        config:
          user-center: #单服务配置
            loggerLevel: full
    ---        
    feign:
      client:
        config:
          default: #全局配置日志级别
            loggerLevel: full
    

    Feign的继承性

    • 官方不建议使用
    • 大多数公司使用?

    架构师需要根据自身业务情况来决定,是否需要将不同的微服务进行业务耦合,还是使用冗余代码的方式来解放业务耦合性。

    Feign多参请求

    Get

    1. 使用@SpringQueryMap
    @FeignClient(name = "user-center")
    public interface ITestUserCenterFeignClient {
    
        @GetMapping("/users/q")
        public UserDTO query(@SpringQueryMap UserDTO userDTO);
    }
    
    1. 使用 @RequestParam
    @FeignClient(name = "user-center")
    public interface ITestUserCenterFeignClient {
    
        @RequestMapping(value = "/users/q",method = RequestMethod.GET)
        public UserDTO query(@RequestParam("id") Long id,@RequestParam("name") String name);
    }
    
    1. 使用Map构建,(不推荐)
    @FeignClient(name = "user-center")
    public interface ITestUserCenterFeignClient {
    
        @RequestMapping(value = "/users/q",method = RequestMethod.GET)
        public UserDTO query(@RequestParam Map<String,Object> conditions);
    }
    

    注意:这种方式不建议使用。主要是因为可读性不好,而且如果参数为空的时候会有一些问题,例如map.put("username", null); 会导致user-center 服务接收到的username是"" ,而不是null。

    Post

    服务提供者方法

        @PostMapping("/create")
        public User createUser(@RequestBody User user){
            return null;
        }
    

    服务调用者

    @FeignClient(name = "user-center")
    public interface ITestUserCenterFeignClient {
    
        @RequestMapping(value = "/users/q",method = RequestMethod.POST)
        public UserDTO query(@RequestBody UserDTO user);
    }
    

    Feign脱离服务注册/Ribbon调用

    @FeignClient(name = "xxxxx",url = "http://www.baidu.com")
    public interface ITestBaiduFeignClient {
    
        @GetMapping("")
        public String getBaidu();
    }
    

    Feign 性能优化

    使用连接池

    httpClient

    1. 加依赖
            <!--Feign 性能优化,需要使用连接池,引入依赖-->
            <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-httpclient</artifactId>
            </dependency>
    
    1. 加注解(不需要)
    2. 改配置
      httpclient:
        # 为feign启用 apache httpclient 做请求,而不使用默认的urlconection
        enabled: true
        # feign 最大连接数
        max-connections: 200
        # feign 单个路径请求的最大连接数
        max-connections-per-route: 50
    

    okHttp

    1. 加依赖
            <!--Feign 性能优化,需要使用连接池,引入依赖-->
            <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-okhttp</artifactId>
            </dependency>
    
    1. 加注解(不需要)
    2. 改配置
      httpclient:
        # 为feign启用 apache httpclient 做请求,而不使用默认的urlconection
        #enabled: true
        # feign 最大连接数
        max-connections: 200
        # feign 单个路径请求的最大连接数
        max-connections-per-route: 50
      okhttp:
        enabled: true
    

    合理使用Feign日志

    生产环境使用Logger.Level.BASIC

    RestTemplate

    RestTemplate VS. Feign

  • 相关阅读:
    【371】Twitter 分类相关
    【370】Python列表生成式(for 写入一行)
    Netbeans 中的编译器相关配置
    SP*
    du 命令
    闲杂
    Shell重定向&>file、2>&1、1>&2的区别
    Shell编程中Shift的用法
    shell中一维数组值得获取
    shell expr的用法
  • 原文地址:https://www.cnblogs.com/zhangpan1244/p/11207822.html
Copyright © 2020-2023  润新知