2023-7-19 feign远程调用学习

一feign与RestTemplate的对比

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

存在下面的问题:

  • 代码可读性差,编程体验不统一

  • 参数复杂URL难以维护

Feign是一个声明式的http客户端,官方地址:https://github.com/OpenFeign/feign

其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。
在这里插入图片描述

二、feign的使用步骤

1 引入依赖

在order-service服务中引入feign的起步依赖

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

2 添加注解

在启动类上添加@EnableFeignClient
在这里插入图片描述

3 编写feign客户端

  1. 在order-service中创建一个包client
  2. 新建一个接口,内容如下:
    1. 指定服务的名字
    2. 指定访问地址
    3. 方法参数的注入
package cn.itcast.order.client;

import cn.itcast.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient("userservice")  //指定服务的名字
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

这个客户端是基于springMVC注解来声明远程调用的信息
服务名称:userservice
请求方式:GET
请求路径:/user/{id}
请求参数:Long id
返回类型:User
这样,Feign就可以帮助我们发送http请求,无需自己使用RestTemplate来发送了。

检查一下order-service中application.yml中nocas服务器地址是否正确,注:注释掉命名空间和集群的配置

spring:
  application:
    name: orderservice

  cloud:
    nacos:
      server-addr: localhost:8488
#      discovery:
#        cluster-name: HZ
#        namespace: a8ace27d-a737-4122-9f3f-92f5ee795b62
#        ephemeral: false

4 测试

修改order-service中的OrderService类中的queryOrderById方法,使用Feign客户端代替RestTemplate:

5 总结

使用Feign的步骤:

① 引入依赖

② 添加@EnableFeignClients注解

③ 编写FeignClient接口

④ 使用FeignClient中定义的方法代替RestTemplate

扩展:查看依赖可以知道feign底层是依赖了ribbon的包
在这里插入图片描述

三 feign的自定义配置

Feign可以支持很多的自定义配置,如下表所示:

类型作用说明
feign.Logger.Level修改日志级别包含四种不同的级别:NONE(默认)、BASIC、HEADERS、FULL
feign.codec.Decoder响应结果的解析器http远程调用的结果做解析,例如解析json字符串为java对象
feign.codec.Encoder请求参数编码将请求参数编码,便于通过http请求发送
feign.Contract支持的注解格式默认是SpringMVC的注解
feign.Retryer失败重试机制请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

一般情况下,默认值就能满足我们使用,如果要自定义时,只需要创建自定义的@Bean覆盖默认Bean即可。

下面以日志为例来演示如何自定义配置。

1 配置文件方式

全局

也可以针对所有服务:default

feign:  
  client:
    config: 
      default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

局部

基于配置文件修改feign的日志级别可以针对单个要调用的服务:

feign:  
  client:
    config: 
      userservice:  # 针对某个微服务的配置
        loggerLevel: BASIC #  日志级别 

注:配置default.loggerLevel的时候idea中没有提示信息,如果同时两个都配置,则优先使用userservice。

要想看到输出的日志信息,需要将系统日志级别设置为debug才能看到。

logging:
  level:
    cn.itcast: debug
feign:
  client:
    config:
      userservice:
        loggerLevel: BASIC
      default:
        loggerLevel: FULL

日志的级别分为四种:

  • NONE:不记录任何日志信息,这是默认值。
  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

配置完成以后,重启服务,在浏览器访问一次,对比一下配置前和配置后的控制台输出的信息

  1. 配置前在这里插入图片描述
  2. 配置FULL后
    在这里插入图片描述

2 java代码方式

也可以基于Java代码来修改日志级别,先声明一个类放在config包中,然后声明一个Logger.Level的对象:

@EnableFeignClients(basePackages = "cn.itcast.demo.client")
@Configuration
public class DefaultFeignConfiguration {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC;
    }
}

全局

如果要全局生效只需要将其放到OrderApplication的@EnableFeignClient中

@EnableFeignClient(defauleFeignClient=DefaultFeignClient.class)

局部

如果只需要作用在局部,只需要将其放在创建的feign客户端的@FeignClient中

@FeignClient(value="userservice",configuration=DefaultFeignConfiguration.class)

四 feign的使用优化

Feign底层发起http请求,依赖于其它的框架。其底层客户端实现包括:

  • URLConnection:默认实现,不支持连接池。每次创建连接要三次握手,结束连接还要四次挥手。

  • Apache HttpClient :支持连接池

  • OKHttp:支持连接池

因此提高Feign的性能主要手段就是使用连接池代替默认的URLConnection。

1. 使用Apache HttpClient之前

FeignClientFactoryBean中的loadBalance方法335行中打断点:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lERR1WFV-1689753715131)(assets/image-20210714185925910.png)]

Debug方式启动order-service服务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ar2XtdSw-1689753715135)(assets/image-20211120102450977.png)]

可以看到这里的client,未配置pom.xml前使用是默认的Client:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3QCTrHme-1689753715137)(assets/image-20211118112658903.png)]

2. 用Apache的HttpClient

1)引入依赖

order-service的pom文件中引入Apache的HttpClient依赖:

<!--httpClient的依赖 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

2)配置连接池

在order-service的application.yml中添加配置,默认是开启的,所以就算没有配置也会一些默认的配置参数

feign:
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

说明:每个不同的微服务连接路径是不同的,如:访问user-service这个微服务就是一条路径,最多有50个连接。通常最大连接数除以一共有多少个微服务,则每个微服务平均占用多少个连接。后期可再根据访问性能的变化进行调整。

  1. 配置后底层就是Apache HttpClient:

注:只有重启的时候会进来一次断点,后面访问就不再进入这个断点了

3. 总结Feign的优化:

1.日志级别尽量用basic

2.使用HttpClient或OKHttp代替URLConnection

① 引入feign-httpClient依赖

② 配置文件开启httpClient功能,设置连接池参数

五 feign的最佳实践

继承方式

一样的代码可以通过继承来共享:

1)定义一个API接口,利用定义方法,并基于SpringMVC注解做声明。

2)Feign客户端和Controller都集成改接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IjEdSr0x-1689753982169)(assets/image-20210714190640857.png)]

优点:
  • 简单
  • 实现了代码共享
缺点:
  • 服务提供方、服务消费方紧耦合

  • 参数列表中的注解映射并不会继承,因此Controller中必须再次声明方法、参数列表的注解

抽取方式

将feign的客户端为一个模块,将与其相关的pojo放入模块中,其他服务要使用该模块只需引用模块依赖到pom文件
在这里插入图片描述

1 抽取

  1)新建一个新模块
在这里插入图片描述

 2)将feign的依赖引入feign-ap

<dependencies>
    <!-- feign的依赖 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!--httpClient的依赖 -->
    <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-httpclient</artifactId>
    </dependency>
</dependencies>

 3)将编写的User,config包,client包导入feign-api模块
在这里插入图片描述
 4)修改代码
UserClient.java

package cn.itcast.demo.client;
import cn.itcast.demo.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = "userservice")
public interface UserClient  {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

DefaultFeignConfiguration.java

package cn.itcast.demo.config;

import feign.Logger;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@EnableFeignClients(basePackages = "cn.itcast.demo.client")
@Configuration
public class DefaultFeignConfiguration {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC;
    }
}

User.java

package cn.itcast.demo.pojo;

import lombok.Data;

@Data
public class User {
    private Long id;
    private String username;
    private String address;
}

 5)
将feign-api install到本地仓库
在这里插入图片描述

2 使用feign-api

首先,删除order-service中的UserClient、User、DefaultFeignConfiguration等类或接口。

在order-service的pom文件中引入feign-api的依赖:

<dependency>
    <groupId>cn.itcast.demo</groupId>
    <artifactId>feign-api</artifactId>
    <version>1.0</version>
</dependency>

3 修改order-service

所有与上述三个组件有关的导包部分,改成导入feign-api中的包。

修改所有导入的User对象为cn.itcast.feign.pojo.User包中的对象

  1. 修改Order
package cn.itcast.order.pojo;

import cn.itcast.feign.pojo.User;
import lombok.Data;

@Data
public class Order {
    private Long id;
    private Long price;
    private String name;
    private Integer num;
    private Long userId;
    private User user;
}
  1. 修改OrderService

    import cn.itcast.feign.client.UserClient;
    import cn.itcast.feign.pojo.User;
    
  2. 重新启动
    发现会报错
    在这里插入图片描述
    原因是feign-api不在SpringbootApplication扫描范围内,有两种解决方案
    指定UserClient所在包
    在这里插入图片描述
    指定UserClient所在包
    在这里插入图片描述
    运行结果
    在这里插入图片描述
    在这里插入图片描述
    这个效果是Microsoft Edge的插件,在扩展商店搜索json,下面随便选一个就可以

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值