Feign远程调用

Feign是代替RestTemplate进行远程调用的组件,避免了RestTemplate手写复杂的url容易出错的问题,并提高代码的可读性

使用Feign步骤

1)引入依赖

哪个服务要发送远程请求就导入在哪个服务

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

2)添加注解

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

3)编写Feign的客户端

在order-service中新建一个接口UserClient,内容如下:①加注解 ②写url语句

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

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

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

4)调用接口

注入接口类对象,调用接口类的方法

自定义配置

Feign可以支持很多的自定义配置,如下表所示:(一般只会修改日志级别来查bug,其他不改)

类型 作用 说明
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)配置文件方式

基于配置文件修改feign的日志级别可以针对单个服务:只有通过当前服务中访问userservice服务时日志会打印

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

也可以针对所有服务:通过当前服务访问的all服务都会打印日志

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

而日志的级别分为四种:

不建议FULL,因为会影响性能。一般是BASIC、NONE(默认)

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

2)Java代码方式

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

该类没有注入到bean所以暂时不起作用。只有当被其他类写入到注解中才生效

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

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

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)

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

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

Feign优化使用

总结,Feign的优化:

1.日志级别尽量用basic

2.使用HttpClient或OKHttp代替URLConnection

① 引入feign-httpClient依赖

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

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

•URLConnection:默认实现,不支持连接池

•Apache HttpClient :支持连接池

•OKHttp:支持连接池

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

这里我们用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:
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:

最佳实践

所谓最近实践,就是使用过程中总结的经验,最好的一种使用方式。

自习观察可以发现,Feign的客户端与服务提供者的controller代码非常相似:

feign客户端:

UserController:

有没有一种办法简化这种重复的代码编写呢?

1、继承方式【不建议】

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

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

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

优点:

  • 简单
  • 实现了代码共享

缺点:

  • 服务提供方、服务消费方紧耦合

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

2、抽取方式

就是将每一个功能业务写成一个小的微服务,然后其他的大业务可以导入依赖调用这些小的微服务,从而减少重复写同样的功能代码

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

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

3、 实现抽取的最佳实践

1)抽取

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

项目结构:

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

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

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

2)在order-service中使用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>

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

3)重启测试

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

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

4)解决跨服务扫描包问题

在启动类上添加注解属性

方式一:

指定Feign应该扫描的包:

@EnableFeignClients(basePackages = "cn.itcast.feign.clients")

方式二:

指定需要加载的Client接口:这里是数组可以放多个参数

@EnableFeignClients(clients = {UserClient.class})

Feign远程调用 (介绍与使用)的更多相关文章

  1. SpringCloud(二) - Eureka注册中心,feign远程调用,hystrix降级和熔断

    1.项目模块介绍 2. 父项目 主要依赖 spring-cloud 的 版本控制 <properties> <!-- springCloud 版本 --> <scd.ve ...

  2. Feign远程调用

    有关微服务中,服务与服务如何通信,我已经给大家介绍了Ribbon远程调用的相关知识,不知道大家有没有发现Ribbon的问题呢? Ribbon的问题 在Ribbon中,如果我们想要发起一个调用,是这样的 ...

  3. springcloud系列五 feign远程调用服务

    一:Feign简介 Feign 是一种声明式.模板化的 HTTP 客户端,在 Spring Cloud 中使用 Feign,可以做到使用 HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完 ...

  4. feign远程调用出错

    如果你传递的参数,比较复杂时,默认会采用POST的请求方式. 传递单个参数时,推荐使用@PathVariable,如果传递的单个参数比较多,这里也可以采用@RequestParam,Feign接口中不 ...

  5. Feign远程调用源码阅读

  6. 阶段5 3.微服务项目【学成在线】_day09 课程预览 Eureka Feign_05-Feign远程调用-客户端负载均衡介绍

    2 Feign远程调用 在前后端分离架构中,服务层被拆分成了很多的微服务,服务与服务之间难免发生交互,比如:课程发布需要调用 CMS服务生成课程静态化页面,本节研究微服务远程调用所使用的技术. 下图是 ...

  7. spring cloud eureka + feign,api远程调用

    网上教程不少,有些就是复制粘贴,不结合实际生产. eureka不再阐述. 一般正常开发会有多个工程,且多个module. 我的习惯是: eureka server.权限.config.gateway ...

  8. SpringCloud使用Nacos服务发现实现远程调用

    本文使用SpringCloud结合Nacos服务发现,Feign远程调用做一个简单的Demo. 1 Nacos 关于Nacos之前写了两篇文章关于SpringBoot对它的使用,感兴趣可以查看一下. ...

  9. 阶段5 3.微服务项目【学成在线】_day09 课程预览 Eureka Feign_07-Feign远程调用-Feign测试

    2.2.1 Feign介绍 Feign是Netflix公司开源的轻量级rest客户端,使用Feign可以非常方便的实现Http 客户端.Spring Cloud引入 Feign并且集成了Ribbon实 ...

  10. JSON-RPC轻量级远程调用协议介绍及使用

    这个项目能够帮助开发人员利用Java编程语言轻松实现JSON-RPC远程调用.jsonrpc4j使用Jackson类库实现Java对象与JSON对象之间的相互转换.jsonrpc4j包含一个JSON- ...

随机推荐

  1. 《Java口袋指南》-内容总结

    Java口袋指南   一.语言   1.命名   类名:大驼峰   泛型:E标识集合元素   方法名:小驼峰   变量名:小写   包名:小写或下划线   2.词法元素/token   字符串压缩优化 ...

  2. 【每日一题】【List与Array互转】【工具类的使用】2021年12月10日-56. 合并区间

    以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] .请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入 ...

  3. go-dongle 0.2.0 版本发布了,一个轻量级、语义化的 golang 编码解码、加密解密库

    dongle 是一个轻量级.语义化.对开发者友好的 Golang 编码解码和加密解密库 Dongle 已被 awesome-go 收录, 如果您觉得不错,请给个 star 吧 github.com/g ...

  4. C++基础语法学习:STL

    基础语法学习,少点比较,多些谦虚 1.容器: 常见的容器有以下几类: 1.vector:向量 2.deque:双端队列 3.list:列表 4.set:集合 5:multiset:多重集合 6.map ...

  5. python运算符与基本数据类型

    Python种类 JavaPython cPython ***** pypy 字节码 和 机器码 Python程序: 1. 终端: C:\python35\python.exe D:\1.py 解释器 ...

  6. 在CentOS8中安装gitlab

    安装 docker 及 docker-compose centos8 更新源 cd /etc/yum.repos.d/ sed -i 's/mirrorlist/#mirrorlist/g' /etc ...

  7. Ubuntu:Docker 容器操作

    创建容器 1.docker run [option] 镜像名 [向启动容器中传入的命令] 常用可选说明 -i 表示以"交互模式"运行容器 -t 表示容器启动后会进入其命令行.加入这 ...

  8. 14、java.sql.SQLException: 无效的列类型: 1111 报错问题解决

    转载自 在项目中利用Mybatis做持久化框架,XXXMapper.xml中insert语句做插入时,偶然会遇到一些报错或者说是问题,如下: 一.报错日志: nested exception is o ...

  9. Python图像处理丨详解图像去雾处理方法

    摘要:本文主要讲解ACE去雾算法.暗通道先验去雾算法以及雾化生成算法. 本文分享自华为云社区<[Python图像处理] 三十.图像预处理之图像去雾详解(ACE算法和暗通道先验去雾算法)丨[拜托了 ...

  10. [python] 向量检索库Faiss使用指北

    Faiss是一个由facebook开发以用于高效相似性搜索和密集向量聚类的库.它能够在任意大小的向量集中进行搜索.它还包含用于评估和参数调整的支持代码.Faiss是用C++编写的,带有Python的完 ...