• http客户端Feign使用


    一、RestTemplate方式调用存在的问题

    先来看我们以前利用RestTemplate发起远程调用的代码:

    String url = "http://userservice/user/" + order.getUserId();
    User user = restTemplate.getForObject(url, User.class);
    
    • 1
    • 2

    存在下面的问题:

    • 代码可读性差,编程体验不统一
    • 参数复杂,URL难以维护

    二、Feign的介绍

    Feign是Spring Cloud提供的声明式的HTTP客户端, 它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。

    Spring Cloud集成Feign并对其进行了增强,使Feign支持了Spring MVC注解;Feign默认集成了Ribbon,所以Fegin默认就实现了负载均衡的效果。

    三、定义和使用Feign客户端

    Feign的使用步骤:

    • 引入依赖
    • 添加@EnableFeignClients注解
    • 编写FeignClient接口(客户端)
    • 使用FeignClient中定义的方法代替RestTemplate

    具体使用Feign的步骤如下,以order-service为例:
    1、在order-service服务中引入依赖:

            
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-openfeignartifactId>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、在order-service服务的启动类添加注解开启Feign的功能:

    @EnableFeignClients
    @MapperScan("cn.itcast.order.mapper")
    @SpringBootApplication
    public class OrderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3、编写Feign客户端:

    @FeignClient("userservice")
    public interface UserClient {
        @GetMapping("/user/{id}")
        User getById(@PathVariable("id") Long id);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    主要是基于SpringMVC的注解来声明远程调用的信息,比如:

    • 服务名称:userservice
    • 请求方式:GET
    • 请求路径:/user/{id}
    • 请求参数:Long id
    • 返回值类型:User

    4、用Feign客户端代替RestTemplate:

        @Autowired
        private UserClient userClient;
        public Order queryOrderById(Long orderId) {
            // 1.查询订单
            Order order = orderMapper.findById(orderId);
            // 2.利用feign 发送http请求,查询用户
            User user = userClient.getById(order.getUserId());
            // 3.封装到order里面
            order.setUser(user);
            // 4.返回
            return order;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    四、自定义Feign的配置

    Feign运行自定义配置来覆盖默认配置,可以修改的配置如下:
    在这里插入图片描述
    一般我们需要配置的就是日志级别。

    配置Feign日志有两种方式:

    方式一:配置文件方式 (相比之下更简单)

    • 全局生效:
    feign:
      client:
        config:
          default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
            logger-level: FULL #  日志级别
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 局部生效:
    feign:
      client:
        config:
          userservice: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
            logger-level: FULL #  日志级别
    
    • 1
    • 2
    • 3
    • 4
    • 5

    方式二:java代码方式,需要先声明一个Bean

    public class FeignClientConfig {
        @Bean
        public Logger.Level feignLogLevel(){
            return Logger.Level.BASIC;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 如果是全局配置,则把它放到@EnableFeignClients这个注解中:
    @EnableFeignClients(defaultConfiguration = FeignClientConfig.class)
    
    • 1
    • 如果是局部配置,则把它放到@FeignClient这个注解中:
    @FeignClient(value = "userservice", configuration = FeignClientConfig.class) 
    
    • 1

    五、Feign的性能优化

    Feign底层的客户端实现:

    • URLConnection:默认是这种实现,不支持连接池,jdk自带,性能不太好,没有连接池,建立连接和销毁的损耗比较大(三次握手,四次挥手)。
    • Apache HttpClient :支持连接池
    • OKHttp:支持连接池

    因此优化Feign的性能主要包括:

    1. 使用连接池代替默认的URLConnection
    2. 日志级别,最好用basic或none

    因此对Feign添加HttpClient的支持,日志级别尽量用basic,步骤如下:
    1、引入httpclient依赖:

            
            <dependency>
                <groupId>io.github.openfeigngroupId>
                <artifactId>feign-httpclientartifactId>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、配置连接池:

    feign:
      client:
        config:
          default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
            logger-level: BASIC #  日志级别
      httpclient:
        enabled: true # 开启feign对HttpClient的支持
        max-connections: 200 # 最大的连接数
        max-connections-per-route: 50 #单个路径最大的连接数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    六、Feign的最佳实践

    1. 方式一(继承):给消费者的FeignClient和提供者的controller定义统一的父接口作为标准。

    在这里插入图片描述
    缺点:

    • 服务紧耦合
    • 父接口参数列表中的映射不会被继承(springmvc)
    1. 方式二(抽取):将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,打成一个jar包,提供给所有消费者,只需要引入依赖就可以使用。
      在这里插入图片描述

    缺点:

    • 模块中的方法对于其他服务可能多余了,用不到。

    实现最佳实践方式二的步骤如下:

    1. 首先创建一个module,命名为feign-api,然后引入feign的starter依赖
    2. 将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中
    3. 在order-service中引入feign-api的依赖
    4. 修改order-service中的所有与上述三个组件有关的import部分,改成导入feign-api中的包重启测试

    这里会出现一个问题,当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用。
    有两种方式解决:

    • 方式一:在@EnableFeignClients注解中添加basePackages,指定FeignClient所在的包。
    @EnableFeignClients(basePackages = "cn.itcast.feign.clients")
    
    • 1
    • 方式二:在@EnableFeignClients注解中添加clients,指定具体FeignClient的字节码。
    @EnableFeignClients(clients = {UserClient.class})
    
    • 1
  • 相关阅读:
    Coredump-N:fprintf第一个参数为空;同步问题
    MySQL数据库管理基本操作(一)
    【数据结构】二叉树的概述
    endnotes插入文献突然变得格式不对,而且也不是按照正常的顺序来插入解决办法
    i.MX 6ULL 驱动开发 二:搭建 KGDB 调试 linux 内核和驱动环境
    大聪明教你学Java | Mysql 为何会引起锁表及其解决办法
    python-docx办公自动化批量生成离职证明
    CSS 渐变彩色字体
    (121)Verilog HDL:设计一个加法功能之Module addsub
    链表——反转链表
  • 原文地址:https://blog.csdn.net/weixin_44925547/article/details/132980952