包含springfeign的词条

本篇文章给大家谈谈springfeign,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

SpringCloud系列——Feign 服务调用

前面我们已经实现了服务的注册与发现(请戳:SpringCloud系列——Eureka 服务注册与发现),并且在注册中心注册了一个服务myspringboot,本文记录多个服务之间使用Feign调用。

GitHub地址:

官方文档:

提供者除了要在注册中心注册之外,不需要引入其他东西,注意以下几点即可:

1、经测试,默认情况下,feign只能通过@RequestBody传对象参数

2、接参只能出现一个复杂对象,例:public Resultlist list(@RequestBody UserVo entityVo) { ... }/list

3、提供者如果又型樱要向其他消费者提供服务,又要向浏览器提供服务,建议保持原先的Controller,新建一个专门给消费者的Controller

测试Controller接口

消费者maven引入jar

配置文件

对日期的解析,消费者要跟提供者一致,不然会报json解析错误

服务调用

1、springdatejpa 应用名称,是服务提供者在eureka注册的名字,Feign会从注册中心获取实例

2、如果不想启动eureka服务,直连本地开发:@FeignClient(name = "springdatejpa", path = "/user/",url = ""),或者无eureka,调用第三方服务,关闭eureka客户端(eureka.client.enabled=false),url直接指定第三方服务地址,path指定路径,接口的方法指定接口

3、如果使用@RequestMapping,最好指定调用方式

4、消费者的返回值必须与提供者的返回值一致,参数对象也要一致

5、2019-05-21补充:如需进行容错处理(服务提供者发生异常),则需要配置fallback,如果需要获取到报错信息,则要配置fallbackFactory ,例:

Feign接口

更多@FeignClient注解参数配置,请参阅官方文档

Controller层

启动类

启动类加入注解:@EnableFeignClients

成功注册两个服务

成功调用

1、启动时报了个SQL错误

解决:配置文件连接数据时指定serverTimezone=GMT%2B8

2、当我将之前搭好的一个springboot-springdata-jpa整合项目在eureka注册时出现了一个报错

然后在网上查了下说是因历握为springboot版本问题(请戳:),之前这个项目用的是2.0.1.RELEASE,现在要在eureka注册,pom引入了就出现了上面的报错

解决:升级了springboot版本,2.1.0,项目正常启动

2019-10-17补充 :Feign设置header请求头

方法1,mapping的headers属性,单一设置

方法2,自定义FeignInterceptor,全局设置

这样就可以设置cookie,传递token等自定义值

常见场景1

通常我们一个服务web层、svc层、dao层,但有时候也会将拆分成两个服务:

web服务提供静态资源、页面以及controller控制器控制跳转,数据通过java调用svc服务获取;

svc服务,进行操作数据库肢租庆以及业务逻辑处理,同时提供接口给web服务调用;

特殊情况下我们想svc服务的接口也做登录校验,所有接口(除了登录请求接口)都有做登录校验判断,未登录的无权访问,这时候就需要做sessionId传递,将web服务的sessionId通过Feign调用时传递到svc服务

web服务

注:登录成功后用sessionId作为key,登录用户的id作为value,保存到redis缓存中

登录拦截器

自定义FeignInterceptor

svc服务

会话期的sessionId,关闭浏览器后就失效了,所以就会退出浏览器后就需要重新登陆,有些情况我们并不想这样,我们想实现七天免登陆,这时候就需要自定义token,并且存放在cookie

登陆拦截器

登陆成功,设置cookie

推出登陆,销毁cookie

代码已经开源、托管到我的GitHub、码云:

GitHub:

码云:

作者:huanzi-qch

出处:

SpringCloud系列之Feign-4.Feign的动态代理

Spring的AOP有两种动态代理方式,其中慧罩一种就是前面讲到的Feign采用前清闹的方式:JDK动态代理。在Spring中通过JdkDynamicAopProxy实现。它有两个特点

 实现InvocationHandler接口,接管invoke方法实现自己的业务逻辑,所有调用都会被传递到InvocationHandler的invoke方法,通过Proxy.newProxyInstance获取动态代理对象

 被代理的对象必须实现了某个接口,不能代理无接口的类。

Spring还有一种动态代理的方式,那就是CGLIB,它并不强制代理类实现某个接口。在实际使用中,CGLIB在代理对象的性能方面比JDKDynamic要快很多,但是在创建代理对象上的时间花费也相当长。所以,正改如果你的类并没有实现接口,或者是单例模式的类不需要重复创建,建议使用CGLIB的方式。

小结

[img]

Spring Cloud Feign使用详解

 通过前面两章对Spring Cloud Ribbon和Spring Cloud Hystrix的介绍庆丛,我们已经掌握了开发微服务应用时,两个重要武器,学会了如何在微服务架构中实现客户端负载均衡的服务调用以及如何通过断路器来保护我们的微服务应用。这两者将被作为基础工具类框架广泛地应用在各个微服务的实现中,不仅包括我们自身的业务类微服务,也包括一些基础设施类微服务(比如网关)。此外,在实践过程中,我们会发现对这两个框架的使用几乎是同时出现的。既然如此,那么是否有更高层次的封装来整合这两个基础工具以简化开发呢?本章我们即将介绍的Spring Cloud Ribbon与Spring Cloud Hystrix,除了提供这两者的强大功能之外,它还提供了一种声明式的Web服务客户端定义方式。

 我们在使用Spring Cloud Ribbon时,通常都会利用它对RestTemplate的请求拦截来实现对依赖服务的接口调用,而RestTemplate已经实现了对HTTP请求的封装处理,形成了一套模版化的调用方法。在之前的例子中,我们只是简单介绍了RestTemplate调用对实现,但是在实际开发中,由于对服务依赖对调用可能不止于一处誉磨樱,往往一个接口会被多处调用,所以我们通常都游肢会针对各个微服务自行封装一些客户端累来包装这些依赖服务的调用。这个时候我们会发现,由于RestTemplate的封装,几乎每一个调用都是简单的模版化内容。综合上述这些情况,Spring Cloud Fegin在此基础上做了进一步封装,由它来帮助我们定义和实现依赖服务接口的定义。在Spring Cloud Feign的实现下,我们只需创建一个接口并用注解的方式来配置它,即可完成对服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。Spring Cloud Feign具备可插拔的注解支持,包括Feign注解和JAX-RS注解。同时,为了适应Spring的广大用户,它在Netflix Feign的基础上扩展了对Spring MVC的注解支持。这对于习惯于Spring MVC的开发者来说,无疑是一个好消息,你我这样可以大大减少学习适应它的成本。另外,对于Feign自身的一些主要组件,比如编码器和解码器等,它也以可插拔的方式提供,在有需求等时候我们以方便扩张和替换它们。

 在本节中,我们将通过一个简单示例来展示Spring Cloud Feign在服务客户端定义所带来的便利。下面等示例将继续使用之前我们实现等hello-service服务,这里我们会通过Spring Cloud Feign提供的声明式服务绑定功能来实现对该服务接口的调用。

▪️首先,创建一个Spring Boot基础工程,取名为kyle-service-feign,并在pom.xml中引入spring-cloud-starter-eureka和spring-cloud-starter-feign依赖,具体内容如下所示。

▪️创建应用主类Application,并通过@EnableFeignClients注解开启Spring Cloud Feign的支持功能。

▪️定义HelloServiceFeign,接口@FeignClient注解指定服务名来绑定服务,然后再使用Spring MVC的注解来绑定具体该服务提供的REST接口。

▪️接着,创建一个RestClientController来实现对Feign客户端的调用。使用@Autowired直接注入上面定义的HelloServiceFeign实例,并在postPerson函数中调用这个绑定了hello-service服务接口的客户端来向该服务发起/hello接口的调用。

▪️最后,同Ribbon实现的服务消费者一样,需要在application.properties中指定服务注册中心,并定义自身的服务名为feign-service-provider,为了方便本地调试与之前的Ribbon消费者区分,端口使用8868。

 发送几次GET请求到 ,可以得到如之前Ribbon实现时一样到效果,正确返回 hi, kyle! i from 10.166.37.142:8877 。依然是利用Ribbon维护了针对HELLO-SERVICE-PROVIDER的服务列表信息,并且通过轮询实现了客户端负载均衡。而与Ribbon不同到是,通过Feign只需定义服务绑定接口,以声明式的方法,优雅而简单地实现了服务调用。

 现实系统中的各种业务接口要比上一节复杂得多,我们会再HTTP的各个位置传入各种不同类型的参数,并且再返回响应的时候也可能是一个复杂的对象结构。再本节中,我们将详细介绍Feign中的不同形式参数的绑定方法。

 再开始介绍Spring Cloud Feign的参数绑定之前,我们先扩张以下服务提供者hello-service-provider。增加下面这些接口,其中包含带有Request参数的请求、带有Header信息的请求、带有RequestBody的请求以及请求响应体中是一个对象的请求。

 在完成了对hello-service-provider的改造之后,下面我们开始在快速入门示例的kyle-service-feign应用中实现这些新增的绑定。

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

 在完成上述改造之后,启动服务注册中心、两个hello-service-privider服务以及我们改造的kyle-service-feign。通过发送GET请求到== ;age=18== ,通过发送POST请求到== ,请求触发HelloServiceFeign对新增接口的调用。最终,我们会获得如下图的结果,代表接口绑定和调试成功。

 由于Spring Cloud Feign的客户端负载均衡是通过Spring Cloud Ribbon实现的,所以我们可以直接配置Ribbon客户端的方式来自定义各个服务客户端调用参数。那么我们如何使用Spring Cloud Feign的工程中使用Ribbon的配置呢?

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

 大多数情况下,我们对于服务调用的超时时间可能会根据实际服务的特性做一些调整,所以仅仅进行个性化配置的方式与使用Spring Cloud Ribbon时的配置方式是意义的,都采用client.ribbon.key=value的格式进行设置。但是,这里就有一个疑问了,cleint所指代的Ribbon客户端在那里呢?

 回想一下,在定义Feign客户端的时候,我们使用了@FeignClient注解。在初始化过程中,Spring Cloud Feign会根据该注解的name属性或value属性指定的服务名,自动创建一个同名的Ribbon客户端。如下:

 Spring Cloud Ribbon默认负载均衡策略是轮询策略,不过该不一定满足我们的需要。Ribbon一共提供了7种负载均衡策略,如果我们需要ZoneAvoidanceRule,首先要在application.properties文件中添加配置,如下所示:

 不过,只是添加了如上配置,还无法实现负载均衡策略的更改。我们还需要实例化该策略,可以在应用主类中直接加入IRule实例的创建,如下:

 想要深入了解Ribbon的原理,或者想详细了解7种负载均衡策略的,可以参考我另一篇博客 《Ribbon详解》 ,我会在博客最下面给出链接。

 从前两节来看在Spring Boot工程中使用Feign,非常的便利。不过实际生产中,在微服务的初期只能从次要系统开始进行改造,可能很多系统由于历史原因仍然是非Spring Boot的工程,然后这些系统如何使用微服务?如何使用注册中心?如何进行负载均衡呢?

 ▪️首先我们在kyle-service-feign创建调用接口OldSystemPostFeign和OldSystemGetFeign,然后使用feign注解提供的相关注解,包含@RequestLine、@Param、@HeaderParam、@Headers等,主要提供了请求方法、请求参数、头信息参数等操作。

 ▪️我们需要脱离Spring Boot和Spring Cloud的支持,使用feign原生的一些东西。在进行Feign封装之前我们需要一些额外的组件,比如编码器。新增组件依赖如下所示:

 ▪️我们需要一个feign-clientproperties文件,来进行ribbon相关的参数配置,配置如下:

 ▪️到目前为止,相关要素已经准备好了,接下来需要feign和ribbon的封装了。我们需要创建OldSystemFeignClientConfiguration类,作用是加载feign-client.properties文件,并创建一个附带负载均衡器的RibbonClient,然后封装出一个附带Jackson编解码器的FeignClient,如下所示:

 ▪️然后我需要一个测试类FeignClientTest,测试以上3个接口,然后将结果输出到控台如下所示:

 ▪️在完成上述改造之后,启动测试类FeignClientTest,获得如下的结果,说明调用使用了负载均衡。

 细心的同学会发现,非Spring Boot使用feign调用根本没有使用到注册中心的服务发现。在此我提供一个思路,我们可以调用代理微服务,再由代理进行服务发现。那么这个代理服务应该具备哪些功能和作用呢?我将会在下一篇博客详细讲述Netflix公司的API网关组件zuul,它承担路由转发,拦截过滤,流量控制等功能。

▪️ 第一次请求失败

 原因:由于spring的懒加载机制导致大量的类只有在真正使用的才会真正创建,由于默认的熔断超时时间(1秒)过短,导致第一次请求很容易失败,特别互相依赖复杂的时候。

 解决方法:提升熔断超时时间和ribbon超时时间,配置如下:

▪️ Feign的Http Client

 Feign在默认情况下使用的是JDK原生URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection。我们可以用Apache的HTTP Client替换Feign原始的http client,从而获取连接池、超时时间等与性能息息相关的控制能力。Spring Cloud从Brixtion.SR5版本开始支持这种替换,首先在项目中声明Apcahe HTTP Client和feign-httpclient依赖,然后在application.properties中添加:

▪️ 如何实现在feign请求之前进行操作

 feign组件提供了请求操作接口RequestInterceptor,实现之后对apply函数进行重写就能对request进行修改,包括header和body操作。

▪️ 请求压缩

 Spring Cloud Feign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。我们只需通过下面两个参数设置,就能开启请求与响应的压缩功能:

 同时,我们还能对请求压缩做一些更细致的设置,比如下面的配置内容指定了压缩的请求数据类型,并设置了压缩的大小下限,只有超过这个大小的请求才会对其进行压缩。

 上述配置的feign.compression.request.nime-types和feign.compression.requestmin-request-size均为默认值。

▪️ 日志配置

 Spring Cloud Feign在构建被@FeignClient注解修饰的服务客户端时,会为每一个客户端都创建一个feign的请求细节。可以在 application.properties 文件中使用logging.level.FeignClient的参数配置格式来开启指定Feign客户端的DEBUG日志,其中FeignClient为Feign客户端定义捷克队完整路径,比如针对本博文中我们实现的HelloServiceFeign可以如下配置开启:

 但是,只是添加了如上配置,还无法实现对DEBUG日志的输出。这时由于Feign客户端默认对Logger.Level对象定义为NONE级别,该界别不会记录任何Feign调用过程中对信息,所以我们需要调整它对级别,针对全局对日志级别,可以在应用主类中直接假如Logger.Level的Bean创建,具体如下:

 在调整日志级别为FULL之后,我们可以再访问第一节的 接口,这是我们在kyle-service-feign的控制台中可以看到类似下面的请求详细的日志:

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

▪️ 负载均衡异常

 当我们只是对一个微服务进行调用的时候,Ribbon提供的支持好像没什么问题。不过在我们进行多个微服务调用时会产生异常,这也是大多数人忽略的。

  情景描述 :2个应用B和C,在A中使用feign client调用B和C;测试结果,假如先调用B,再调用C都是有效的,但是再调用B就是无效的;(B,C先后顺序改变,都会产生这个bug)

  解决方法 :在主启动类使用注解@RibbonClient,进行RibbonClient配置,如下所示:

 看不懂是吗?不要紧,我下面详细讲解一下,先看一下我们之前的非Spring Boot工程中封装FeignClient:

 OldSystemPostFeign只是一个接口,Feign为什么需要使用接口来调用远程接口?原因就是使用JDK动态代理,我们可以去看Feign是如何进行处理。

SpringCloud系列之Feign-6.Feign上下文构建解析

1.首先在构建上下文的入口是在FeignClientFactoryBean的getObject方法

2.首先第一步就是构建了FeignContext类

3.然后我们进入到feign这个方法中看下:

可以看到首先获取两个日志对象一个FeignLoggerFactory,一个Logger,然后就是把这两个日志对象赋值给feign这个对象,我们看的Builder其实类似于方法糖,让赋值更加方便而已,类似于lombok中的@builder注解一样。

除了赋值日志对象以外,还有加密解密的一个赋值操作,这个是url解析过程中也是非常常见的。然后其他的我们暂时不关注,只要知道这里是初始化了feign对象,一个空的对象,构造器。

4.然后我们继续在主方法往下走

在上一个帖子上我们注意到url是空的,那么在这里就需要使用到了,从源码中看到如果url是空的,那么就使用服务名称作为ip了,然后如果不是http开头,这里就会给一个http的前缀上去,因为feign也是基于eureka的http接口的。

我们在看下下一个方法啊 cleanPaht();

这里其实还是拼装url的操作,在@FeignClient注解中有一个path的属性,这个属性干嘛用的呢,如图:

而这个path我们最后是不需要/的,所以这里其实就是格式化一下而已,正确的拼接好url的操作。

5.主方法继续

这里就是构造动态代理对象的地方了。

我们点进去腔芦看:

可以看到首先调用了getOptional这个方法,然后使用了

传入了一个调用的服务名称就是 eureka-client这个服务名称,还有一个 feign.Client的类。

其实这个方法就是从上下文中拿到调用了这个服务的接口作为一个client。

然后把client放到Feign对象中,再构建一个Targeter类

6.然后我们进入targeter.target这个方法看看这个最核心的地方

这块逻辑做了一个判断,看这个feign是不是hystrix的feign,如果是就走上面的逻辑,否则就走下面的逻辑,降级熔断啊之类竖念的逻辑,但我们注意到不论走哪个,最终都会走feign.target(target);

7.然后我们进入 feign.target 这个方法:

我们继续进入newInstance这个方法:

上面的三个方法没看懂,我们暂且跳过,看到target通过断点我们可以知道,type就是IService,getMethods就是获取到了FeignClient那个接口下面的所有方法了,现在就是遍历所有方法了,我们现在懂点看下遍历中做的逻辑是什么

8.首先进行判断,看他是对象吗,显然这个是方法不是对象所以跳过,然后Util.isDefault(method)我们看下:

看着大致意思就是判断这个是不是接口而且修饰符必须是这几种;

所以这个判断也没进去,最后执行了下面这个方法:

我们查看下Feign.configKey(target.type(), method) 这个是什么:

发现是这个FeignClient接口的名称#方法名称;

所以这里就在methodToHandler.put如一个方法,还有方法的Handler,所以说这个伍纤带接口虽然没有实现类,但是转发到了其他的实现类中,那么这个实现类到底是什么,我们继续往下面看:

然后就把这个handler作为参数创建了一个代理proxy并返回,然后如果我们通过Feign访问的话其实访问的就是代理proxy,但是最终干活的其实就是handler。

Spring Cloud中优雅的使用Feign调用接口

1、RestTemplate来调用接口

可以直接注入对象槐蠢,然后调用接口,这种方式唯一的弊端就是你需要知道服务提供者的地址,根据指定的地址来进行调用

@Autowired

private RestTemplate restTemplate;

@Override

public SubstitutionDto getSubstitutionInfo(Long sid) {

    User user= this.restTemplate.getForObject("" + id, User.class);

  // .......

}

2、声明式的REST客户端Feign来进行接口调用

在启动类上加 @EnableFeignClients 注解,如果你的Feign接口定义跟你的启迅谨动类不在一个包名下,还需要制定扫描的包名 @EnableFeignClients (basePackages = "com.hui.api.client")

接口的消费定义,单独抽一个项目出来,后面打成公亩明基共的jar,这样无论是哪个项目需要调用接口,引入公共的接口SDK jar即可,不用重新定义一遍了。

关于springfeign和的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

标签列表