SpringCloud-Feign远程调用

使用Feign替代RestTemplate进行远程服务调用:

远程调用配置

1. 引入依赖

我们在order-service服务的pom文件中引入feign的依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2. 添加注解

在启动类添加注解开启Feign的功能:@EnableFeignClients

3. 编写Feign的客户端

在order-service中新建一个接口,内容如下:

java 复制代码
@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来发送了。

4. 测试

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

是不是看起来优雅多了。

5. 总结

使用Feign的步骤:

① 引入依赖

② 添加@EnableFeignClients注解

③ 编写FeignClient接口

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

Feign-自定义配置

1.介绍

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即可。

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

2. 两种配置方式

1) 配置文件方式

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

yaml 复制代码
feign:  
  client:
    config: 
      userservice: # 针对某个微服务的配置
        loggerLevel: FULL #  日志级别

也可以针对所有服务:

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

而日志的级别分为四种:

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

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

java 复制代码
public class DefaultFeignConfiguration  {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}

如果要全局生效,将其放到启动类的@EnableFeignClients这个注解中:

java 复制代码
@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)

如果是局部生效,则把它放到对应的@FeignClient这个注解中:

java 复制代码
@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)

Feign使用优化

1. 优化分析

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

  • URLConnection:默认实现,不支持连接池(默认)
  • Apache HttpClient :支持连接池
  • OKHttp:支持连接池

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

因此优化Feign性能只要:

  • 使用连接池代替默认的URLConnection。
  • 设置合适的日志级别,最好使用basic或none。

2.优化设置

这里我们用Apache的HttpClient来演示。

1)引入依赖

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

xml 复制代码
<!--httpClient的依赖 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>
2)配置连接池

在order-service的application.yml中添加配置:

yaml 复制代码
feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

接下来,在FeignClientFactoryBean中的loadBalance方法中打断点:

Debug方式启动order-service服务,可以看到这里的client,底层就是Apache HttpClient;

3)总结

Feign的优化:

1.日志级别尽量用basic

2.使用HttpClient或OKHttp代替URLConnection

① 引入feign-httpClient依赖

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

使用-最佳实践

两种方式: (推荐使用第二种方式)

1. 继承方式

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

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

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

优点:

  • 简单
  • 实现了代码共享

缺点:

  • 服务提供方、服务消费方紧耦合
  • 参数列表中的注解映射并不会继承,因此Controller中必须再次声明方法、参数列表、注解

2. 抽取方式

1)介绍

将Feign的Client抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用。

例如,将UserClient、User、Feign的默认配置都抽取到一个feign-api包中,所有微服务引用该依赖包,即可直接使用。

2)实现基于抽取的最佳实践案例
1. 创建新模块(.抽取)

首先创建一个module,命名为feign-api:

项目结构:

2. 引入依赖

在feign-api中然后引入feign的starter依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
3 .配置必要数据

然后,order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中

上面已经完成了抽取,下面就是开始进行使用配置

4. 开始使用

首先,如果有之前残留的配置,删除order-service中的UserClient、User、DefaultFeignConfiguration等类或接口。

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

xml 复制代码
<dependency>
    <groupId>cn.itcast.demo</groupId>
    <artifactId>feign-api</artifactId>
    <version>1.0</version>
</dependency>

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

5. 重启测试

重启后,发现服务报错了:

这是因为UserClient现在在cn.itcast.feign.clients包下,

而order-service的@EnableFeignClients注解是在cn.itcast.order包下,不在同一个包,无法扫描到UserClient。

6. 解决扫描包问题

方式一:

指定Feign应该扫描的包:

java 复制代码
@EnableFeignClients(basePackages = "cn.itcast.feign.clients")

方式二:(这里使用方式二)

指定需要加载的Client接口:

java 复制代码
@EnableFeignClients(clients = {UserClient.class})
相关推荐
北辰浮光17 分钟前
[springboot]SSM日期数据转换易见问题
java·spring boot·后端
木梓辛铭24 分钟前
Spring Cache的详细使用
java·后端·spring
bing_1582 小时前
Spring MVC 拦截器 (HandlerInterceptor) 是什么? 它与 Servlet Filter 有什么区别?
spring·servlet·mvc
薯条不要番茄酱2 小时前
【SpringBoot】从零开始全面解析SpringMVC (二)
java·spring boot·后端
小林学习编程2 小时前
Springboot考研信息平台
spring boot·后端·考研
长勺3 小时前
Spring Security vs Shiro vs Sa-Token
java·后端·spring
yezipi耶不耶3 小时前
Rust入门之高级Trait
开发语言·后端·rust
qq_12498707534 小时前
原生小程序+springboot+vue+协同过滤算法的音乐推荐系统(源码+论文+讲解+安装+部署+调试)
java·spring boot·后端·小程序·毕业设计·课程设计·协同过滤
后青春期的诗go4 小时前
基于Rust语言的Rocket框架和Sqlx库开发WebAPI项目记录(一)
开发语言·后端·rust
信徒_5 小时前
SpringBoot 自动装配流程
java·spring boot·后端