前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spring cloud服务间调用之feign

spring cloud服务间调用之feign

作者头像
丁D
发布2022-08-12 20:50:22
8840
发布2022-08-12 20:50:22
举报
文章被收录于专栏:老铁丁D

概述

在微服务架构盛行的年代,我们将一个大型的系统,拆解成各个服务,要完成一个业务逻辑,就可能需要,调用不同服务。比如订单服务调用会员服务。当然我们可以使用JDK自带的URLConnection,或者Apache的Http Client来调用,但是最为优雅的使用feign。

Feign可以使我们调用远程服务跟调用本地方法一样,完全感知不到这是调用远程方法,更感知不到这个一个http请求。

Feign结合了Ribbon的负载均衡

Feign结合了Hystrix可以实现熔断,降级

Feign可以进行GZIP压缩。

Feign工作原理

程序启动的时候会自动FeignClients的注解的类,并注入spring ioc容器中,当定义的feign接口的方法被调用时,会使用JDK的动态代理,生成RequestTemplate,当生成代理时,会为每个接口方法建立一个RequestTemplate对象,这个对象封装了Http请求需要的信息,比如参数,请求方法等。

RequestTemplate生成request对象,将request交给client处理,这里的client默认是JDK原生的URLConnection、Apache的Http Client,当然可以是OKhttp,之后client会被封装成LoadBalanceClient,这个类结合ribbon提供负载均衡发起服务之间的调用。

Feign入门案例

1.引入依赖

代码语言:javascript
复制
<dependency> 
<groupId>org.springframework.cloud</groupId> 
<artifactId>spring-cloud-starter-openfeign</artifactId> 
</dependency> 

2.启动类通过注解开启

代码语言:javascript
复制
/** 
* 會員服務 
* 
*/ 
@SpringBootApplication(scanBasePackages = { "com.ding" }) 
@EnableDiscoveryClient 
@EnableFeignClients 
public class MemberApplication { 
public static void main(String[] args) { 
SpringApplication.run(MemberApplication.class, args); 
} 
} 

其中@EnableFeignClients注解表示当项目启动的时候,会自动扫描@FeignClient的类,进行处理

3.编写接口

代码语言:javascript
复制
package com.ding.member.api; 
import org.springframework.cloud.openfeign.FeignClient; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.RequestParam; 
import com.ding.core.Result; 
import com.ding.member.dto.MemberDto; 
import com.ding.member.hystrix.MemberQueryFeignHystrix; 
@FeignClient(value ="cloud-member",fallback=MemberQueryFeignHystrix.class) 
public interface MemberQueryFeignApi { 
@RequestMapping(value = "/memberQueryFeign/getMemberById",method=RequestMethod.GET) 
Result<MemberDto> getMemberById(@RequestParam(value = "memberId")Long memberId); 
} 

feign超时

https://www.136.la/jingpin/show-210022.html

feign超时分为两种 1、ribbon超时 2、hystrix超时,高版本默认是关闭hystrix ribbon超时

hystrix超时

注意:Hystrix和Ribbon的超时时间,较小的值生效,Hystrix超时时间要设置比Ribbon大,不然熔断失效。 ribbon 总超时时间(conn_time+read_time)(MaxAutoRetries + 1) (MaxAutoRetriesServer + 1)

Feign默认clinet的替换

feign默认使用JDK原生的URLConnection发送Http请求,没有连接池。但是对每个地址保持一个长连接。我们可以使用Apache的HttpClient来替换,通过设置连接池,超时时间等来优化

使用apache的httpclient来替换 1、引入依赖

2、修改配置文件

使用okhttp来替换

1、引入依赖

2、修改配置文件

使用post和get传递实体参数

在实际开发中我们经常将多个参数封装成一个POJO,用于参数的接受 ,在spring mvc中get请求是可以直接绑定POJO的,但是在feign中get请求是不能这样弄的。。post请求可以 addUser(User user) 解决方案 1.将参数拆成一个个独立的属性,放在方法参数列表中 addUser(Integer age,String name) 2.将参数变成一个Map进行传递和接收 3.使用get请求传递@RequestBody,但是这个方式违反了restful规范 addUser(@RequestBody User user) 4.使用feign的拦截器 通过实现feign的RequestInterceptor的apply方法,统一拦截使用get方法并且使用body传递参数

注意 这里一定要注意,再定义各参数绑定时,@RequestParam@RequestHeader等可以指定参数名称的主角,它们的value千万不能少。在Spring MVC程序中,这些注解会根据参数名来作为默认值,但是在Feign中绑定参数必须通过value属性来指明具体的参数名,不然会抛出==IllegalStateException==异常,value属性不能为空。addUser(@RequestParam String name)会报错要addUser(@RequestParam(”name”) String name)或者addUser(@RequestParam(value=”name”) String name)

第一次请求失败

当feign结合了Ribbon和Hystrix之后,可能会出现首次调用超时失败。原因:hystrix默认超时时间为1秒,如果这个时间之内没有响应,就会进入fallback方法,进行熔断。。而spring的懒加载机制,bean的加载和装配都要再使用的使用才执行,所以feign首次请求会比较慢,从而出现这个问题。 方案:延长熔断时间

代码语言:javascript
复制
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds= 

全局配置

全局配置的方法非常简单,我们可以直接使用ribbon.key=value的方式来设置ribbon的各项默认参数。如下:

代码语言:javascript
复制
#以下配置全局有效 
ribbon.eureka.enabled=true 
#建立连接超时时间,原1000 
ribbon.ConnectTimeout=60000 
#请求处理的超时时间,5分钟 
ribbon.ReadTimeout=60000 
#所有操作都重试 
ribbon.OkToRetryOnAllOperations=true 
#重试发生,更换节点数最大值 
ribbon.MaxAutoRetriesNextServer=10 
#单个节点重试最大值 
ribbon.MaxAutoRetries=1 

很多情况下,我们需要个性化设置,比如设置每个服务有不同的配置client.ribbon.key=value

代码语言:javascript
复制
#以下配置对服务cloud-member有效 
cloud-member.ribbon.eureka.enabled=true 
#建立连接超时时间,原1000 
cloud-member.ribbon.ConnectTimeout=60000 
#请求处理的超时时间,5分钟 
cloud-member.ribbon.ReadTimeout=60000 
#所有操作都重试 
cloud-member.ribbon.OkToRetryOnAllOperations=true 
#重试发生,更换节点数最大值 
cloud-member.ribbon.MaxAutoRetriesNextServer=10 
#单个节点重试最大值 
cloud-member.ribbon.MaxAutoRetries=1 

传递token

很多情况下,我们会发现当我们外部请求,经过网关—到达服务A(token可以取到)—到达服务B(token丢失)这样会导致我们token验证失败,我们可以使用拦截器来处理

开启feign调用日志

我们可以为每个feign client开启日志。 可以在application.properties文件中使用logging.level.FeignClient的参数配置格式来开启指定Feign客户端的DEBUG日志

代码语言:javascript
复制
@FeignClient(value ="cloud-member",fallback=MemberQueryFeignHystrix.class) 
public interface MemberQueryFeignApi { 
@RequestMapping(value = "/memberQueryFeign/getMemberById",method=RequestMethod.GET) 
Result<MemberDto> getMemberById(@RequestParam(value = "memberId")Long memberId); 
} 

如上面 我们可以在配置文件

代码语言:javascript
复制
logging.level.com.ding.member.api.MemberQueryFeignApi=DEBUG 

只是添加了如上配置,还无法实现对DEBUG日志的输出。这时由于Feign客户端默认对Logger.Level对象定义为NONE级别,该界别不会记录任何Feign调用过程中对信息,所以我们需要调整它对级别

代码语言:javascript
复制
@EnableEurekaClient 
@SpringBootApplication 
@EnableFeignClients 
public class Application { 
public static void main(String[] args) { 
SpringApplication.run(Application.class, args); 
} 
@Bean 
public Logger.Level feignLoggerLevel() { 
return Logger.Level.FULL; 
} 
} 

对于Feign的Logger级别主要有下面4类,可根据实际需要进行调整使用。

  • NONE:不记录任何信息。
  • BASIC:仅记录请求方法、URL以及响应状态码和执行时间。
  • HEADERS:出了记录BASIC级别的信息之外,还会记录请求和响应的头信息。
  • FULL:记录所有请求与响应的细节,包括头信息、请求体、元数据等。

参考 《重新定义spring cloudSpring Cloud Feign使用详解

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-05-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • Feign工作原理
  • Feign入门案例
  • feign超时
  • Feign默认clinet的替换
  • 使用post和get传递实体参数
  • 第一次请求失败
  • 全局配置
  • 传递token
  • 开启feign调用日志
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档