专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Feign 实战-> 源码

一、Feign简介

Feign是Netflix开发的⼀个轻量级RESTful的HTTP服务客户端(⽤它来发起请求,远程调⽤的),是以Java接⼝注解的⽅式调⽤Http请求,⽽不⽤像Java中通过封装HTTP请求报⽂的⽅式直接调⽤,Feign被⼴泛应⽤在Spring Cloud 的解决⽅案中。 类似于Dubbo,服务消费者拿到服务提供者的接⼝,然后像调⽤本地接⼝⽅法⼀样去调⽤,实际发出的是远程的请求。

常规的RestTemplate请求存在拼接url restTmplate.getForObJect比较模版化,硬编码等不便之处。

  • Feign可帮助我们更加便捷,优雅的调⽤HTTP API:不需要我们去拼接url然后呢调⽤ restTemplate的api,在SpringCloud中,使⽤Feign⾮常简单,创建⼀个接⼝(在消费者–服务调⽤⽅这⼀端),并在接⼝上添加⼀些注解,代码就完成了
  • SpringCloud对Feign进⾏了增强,使Feign⽀持了SpringMVC注解(OpenFeign)

本质:封装了Http调⽤流程,更符合⾯向接⼝化的编程习惯,类似于Dubbo的服务调⽤ Dubbo的调⽤⽅式其实就是很好的⾯向接⼝编程

二、 Feign配置应⽤

Feign = RestTemplate+Ribbon+Hystrix

  • 消费者引⼊Feign依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

  • 消费者启动类使⽤注解@EnableFeignClients添加Feign⽀持 @EnableFeignClients,注意:此时去掉Hystrix熔断的⽀持注解@EnableCircuitBreaker即可包括引⼊的依赖,因为Feign会⾃动引⼊
  • 创建Feign接⼝
// name:调⽤的服务名称,和服务提供者yml⽂件中spring.application.name保持⼀致
@FeignClient(name="lagou-service-resume")
public interface ResumeFeignClient {
//调⽤的请求路径
@RequestMapping(value = "/resume/openstate/{userId}",method=
RequestMethod.GET)
    public Integer findResumeOpenState(@PathVariable(value = "userId")
Long userId);
}

注意:

1、 @FeignClient注解的name属性⽤于指定要调⽤的服务提供者名称,和服务提供者yml⽂件中 spring.application.name保持⼀致
2、 接⼝中的接⼝⽅法,就好⽐是远程服务提供者Controller中的Hander⽅法(只不过如同本地调⽤了),那么在进⾏参数绑定的时,可以使⽤@PathVariable、@RequestParam、@RequestHeader等,这也是OpenFeign对SpringMVC注解的⽀持,但是需要注意value必须设置,否则会抛出异常

  • 使⽤接⼝中⽅法完成远程调⽤
@Autowired
private ResumeFeignClient resumeFeignClient;
@Test
public void testFeignClient(){
    Integer resumeOpenState =
    resumeFeignClient.findResumeOpenState(1545132l);
    System.out.println("=======>>>resumeOpenState:" + resumeOpenState);
}

三、Feign对负载均衡的⽀持

Feign 本身已经集成了Ribbon依赖和⾃动配置,因此我们不需要额外引⼊依赖,可以通过 ribbon.xx 来进 ⾏全局配置,也可以通过服务名.ribbon.xx 来对指定服务进⾏细节配置配置(参考之前,此处略) Feign默认的请求处理超时时⻓1s,有时候我们的业务确实执⾏的需要⼀定时间,那么这个时候,我们就需要调整请求处理超时时⻓,Feign⾃⼰有超时设置,如果配置Ribbon的超时,则会以Ribbon的为准

  • Ribbon设置
#针对的被调⽤⽅微服务名称,不加就是全局⽣效
lagou-service-resume:
    ribbon:
        #请求连接超时时间
        #ConnectTimeout: 2000
        #请求处理超时时间
        #ReadTimeout: 5000
        #对所有操作都进⾏重试
        OkToRetryOnAllOperations: true
        ####根据如上配置,当访问到故障请求的时候,它会再尝试访问⼀次当前实例(次数由
        MaxAutoRetries配置),
        ####如果不⾏,就换⼀个实例进⾏访问,如果还不⾏,再换⼀次实例访问(更换次数由
        MaxAutoRetriesNextServer配置),
        ####如果依然不⾏,返回失败信息。
        MaxAutoRetries: 0 #对当前选中实例重试次数,不包括第⼀次调⽤
        MaxAutoRetriesNextServer: 0 #切换实例的重试次数
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #负载
        策略调整

四、Feign对熔断器的⽀持

  • 在Feign客户端⼯程配置⽂件(application.yml)中开启Feign对熔断器的⽀持
# 开启Feign的熔断功能
feign:
  hystrix:
   enabled: true

注意:

1、 开启Hystrix之后,Feign中的⽅法都会被进⾏⼀个管理了,⼀旦出现问题就进⼊对应的回退逻辑处理
2、 针对超时这⼀点,当前有两个超时时间设置(Feign/hystrix),熔断的时候是根据这两个时间的最 ⼩值来进⾏的,即处理时⻓超过最短的那个超时时间了就熔断进⼊回退降级逻辑

86_1.png

  • ⾃定义FallBack处理类(需要实现FeignClient接⼝)

86_2.png

  • 在@FeignClient注解中关联2)中⾃定义的处理类
@FeignClient(value = "lagou-service-resume",fallback =
ResumeFallback.class,path = "/resume") // 使⽤fallback的时候,类上的
@RequestMapping的url前缀限定,改成配置在@FeignClient的path属性中
//@RequestMapping("/resume")
public interface ResumeServiceFeignClient {

五、Feign对请求压缩和响应压缩的⽀持

Feign ⽀持对请求和响应进⾏GZIP压缩,以减少通信过程中的性能损耗。通过下⾯的参数 即可开启请求与响应的压缩功能:

86_3.png

六、Feign的⽇志级别配置

Feign是http请求客户端,类似于咱们的浏览器,它在请求和接收响应的时候,可以打印出⽐较详细的⼀些⽇志信息(响应头,状态码等等),默认情况下Feign的⽇志没有开启。

  • 开启Feign⽇志功能及级别
// Feign的⽇志级别(Feign请求过程信息)
// NONE:默认的,不显示任何⽇志----性能最好
// BASIC:仅记录请求⽅法、URL、响应状态码以及执⾏时间----⽣产问题追踪
// HEADERS:在BASIC级别的基础上,记录请求和响应的header
// FULL:记录请求和响应的header、body和元数据----适⽤于开发及测试环境定位问题
@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLevel() {
        return Logger.Level.FULL;
    }
}

  • 配置log⽇志级别为debug
logging:
  level:
   # Feign⽇志只会对⽇志级别为debug的做出响应
   com.lagou.edu.controller.service.ResumeServiceFeignClient: debug

七、Feign核⼼源码剖析

思考⼀个问题:只定义了接⼝,添加上@FeignClient,真的没有实现的话,能完成远程请求么?不能,考虑是做了代理了。

  • 断点标注 @FeginClient 接口

86_4.png

  • 从@EnableFeignClients 正向切⼊
  • import FeignClientsRegistrar
  • 进入 org.springframework.cloud.openfeign.FeignClientsRegistrar#registerBeanDefinitions,重写BeanDefinitions,完成Bean 注入
  • 接下来,我们主要追踪下另外⼀⾏主要的代码registerFeignClients(metadata, registry);定义了扫描器,主要扫描@FeginClient
  • 注册客户端,给每⼀个客户端⽣成代理对象
  • 所以,下⼀步,关注FeignClientFactoryBean这个⼯⼚Bean的getObject⽅法,根据经验,这个⽅法会返回我们的代理对象
  • getObject 里面完成了 核心方法,包括了负载均衡的封装,最后发起请求
  • 最终请求的发起使⽤的是HttpURLConnection

简单总结下:

为标注@FeginClient的接口生成代理,封装成Bean,利用FactoryBean#getObject,去包装了Ribbon,最终发起http请求。

lagouedu 笔记总结

文章永久链接:https://tech.souyunku.com/29256

未经允许不得转载:搜云库技术团队 » Feign 实战-> 源码

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们