`

跟我学Spring Cloud(Finchley版)-09-Feign

 
阅读更多

说明:SpringCloud系列笔者自学系列,学习来源是周立的博客  http://www.itmuch.com/ 。而此处转载其博客只是为了方便自己以后的学习。

本篇来源 http://www.itmuch.com/spring-cloud/finchley-9/

 

经过前文讲解,我们已使用Eureka实现服务发现;使用Ribbon实现了负载均衡这种听起来很高端的东西。我们的架构已经初具雏形,但依然存在很多问题,下面不妨来分析下前文的代码——

 
@GetMapping("/users/{id}")
public User findById(@PathVariable Long id) {
  // 这里用到了RestTemplate的占位符能力
  User user = this.restTemplate.getForObject(
    "http://microservice-provider-user/users/{id}",
    User.class,
    id
  );
  // ...电影微服务的业务...
  return user;
}

这里,this.restTemplate.getForObject("http://microservice-provider-user/users/{id}"…这行代码是比较糟糕的,存在诸多问题——

  • 如果系统业务非常复杂,而你是一个新人,当你看到这行代码,恐怕很难一眼看出其用途是什么!此时,你很可能需要寻求老同事的帮助(往往是这行代码的作者,哈哈哈,可万一离职了呢?),或者查阅该目标地址对应的文档(文档常常还和代码不匹配,哈哈哈),才能清晰了解这行代码背后的含义!否则,你只能陷入蛋疼的境地!
  • 这个例子构造的URL非常简单,但如果你需要构造类似如下这么丑陋的URL时(原谅我老是拿百度开涮,其实我没有恶意):https://www.baidu.com/s?wd=asf&rsv_spt=1&rsv_iqid=0xa25bbeba000047fd&issp=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=3&rsv_sug1=2&rsv_sug7=100&rsv_sug2=0&inputT=328&rsv_sug4=328,恐怕就有心无力了!尽管RestTemplate支持使用占位符,从而让我们避免字符串拼接的尴尬境地,但构造这么复杂的URL依然是很麻烦的。更可怕的是,互联网时代需求变化非常之快,你的参数可能会从10个变成12个、15个,再后来又精简成13个……维护这个URL真的是想想都累……总而言之,复杂URL的构造会让你处于一种不性福的状态

铺垫了这么多,如何解决以上问题?用Feign!

TIPS

  • Feign本质上来说是个山寨,其设计思想基本都来源于Retrofit(使用方式更是如出一辙)
  • Retrofit的GitHub:https://github.com/square/retrofit ,如果你知道Square公司,那么你很厉害!是的,Retrofit也是开源OKHttp的那家公司开源的——所以,笔者喜欢将Square公司称为‘’HTTP客户端小王子”,但其实人家是做移动支付的。
  • Spring Cloud对Retrofit也有支持https://github.com/spring-cloud-incubator/spring-cloud-square ,目前正在孵化中,有兴趣的可以去体验一下。学会Feign后,Retrofit上手也就是5分钟的事情。

简介

Feign是Netflix开发的声明式、模板化的HTTP客户端,其灵感来自Retrofit、JAXRS-2.0以及WebSocket。Feign可帮助我们更加便捷、优雅地调用HTTP API。

在Spring Cloud中,使用Feign非常简单——只需创建接口,并在接口上添加注解即可。

Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。Spring Cloud对Feign进行了增强,使其支持Spring MVC注解,另外还整合了Ribbon和Eureka,从而使得Feign的使用更加方便。

TIPS

Feign的GitHub:https://github.com/OpenFeign/feign

Quick Start

下面来将前面的例子用Feign改写,让其达到与Ribbon + RestTemplate相同的效果。

  • 复制项目microservice-consumer-movie,将ArtifactId修改为microservice-consumer-movie-feign 

  • 加依赖:

     
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
  • 加注解:启动类上添加@EnableFeignClients 

  • 编写Feign Client:

     
    @FeignClient(name = "microservice-provider-user")
    public interface UserFeignClient {
      @GetMapping("/users/{id}")
      User findById(@PathVariable("id") Long id);
    }

    这样一个Feign Client就写完啦!其中,@FeignClient 注解中的microservice-provider-user是想要请求服务的名称,这是用来创建Ribbon Client的(Feign整合了Ribbon)。在本例中,由于使用了Eureka,所以Ribbon会把microservice-provider-user 解析成Eureka Server中的服务。

    除此之外,还可使用url属性指定请求的URL(URL可以是完整的URL或主机名),例如@FeignClient(name = "abcde", url = "http://localhost:8000/") 。此时,name可以是任意值,但不可省略,否则应用将无法启动!

  • Controller:

     
    @RequestMapping("/movies")
    @RestController
    public class MovieController {
      @Autowired
      private UserFeignClient userFeignClient;
    
      @GetMapping("/users/{id}")
      public User findById(@PathVariable Long id) {
        return this.userFeignClient.findById(id);
      }
    }

    只需使用@Autowire注解,即可注入上面编写的Feign Client。

RestTemplate与Feign对比

相信通过本文的例子,聪明的你对如何使用Feign已经了然于心了。文章的最后,对比一下RestTemplate + Ribbon与Feign。

角度 RestTemplate + Ribbon Feign(自带Ribbon)
可读性、可维护性 欠佳(无法从URL直观了解这个远程调用是干什么的) 极佳(能在接口上写注释,方法名称也是可读的,能一眼看出这个远程调用是干什么的)
开发体验 欠佳(拼凑URL不性福 极佳(写出漂亮的代码,女朋友更爱你了
风格一致性 欠佳(本地API调用和RestTemplate调用的代码风格截然不同) 极佳(完全一致,不点开Feign的接口,根本不会察觉这是一个远程调用而非本地API调用)
性能 较好 中等(性能是RestTemplate的50%左右;如果为Feign配置连接池,性能可提升15%左右)
灵活性 极佳 中等(内置功能能满足大多数项目的需求)

那么如何选择呢?相信这才是大家最关注的问题!

笔者认为——

  • 一般来说,建议使用Feign,并杜绝使用RestTmplate。为什么用Feign相信不必啰嗦;可为什么要杜绝RestTemplate,那是因为在一个项目里,保持统一的编码风格乃至体验,是非常重要的。我个人的架构原则是尽量减少开发人员的选择,如果A能解决问题,就杜绝使用B——最佳实践永远只有一个!并且,共存带来的往往不是相得益彰,反而是歧义、错乱以及额外的学习成本、理解成本(笔者当年参与过一个同时使用Struts1 + Struts2 + Servlet的项目,可以想象一下学习成本有多高;笔者还参与一个一个使用Jackson + FastJson + json-lib + Gson的项目,可想而知操作JSON的代码有多混乱……80%的开发在骂娘中度过时光,并抨击别人使用他不熟悉的JSON操作库,后来被笔者统一成Jackson后,大家都安心干活了)!
  • 有人可能会对Feign的性能存在顾虑,笔者认为,Feign的性能虽然不那么优秀,但大部分场景下都是OK的——项目的性能瓶颈一般都不出在HTTP客户端上,而在于自身业务的处理!
  • 求同存异——上文虽说要杜绝RestTemplate,但事无绝对,你得根据具体情况具体分析——对于某些变态需求,在使用Feign很难实现或无法实现时,可考虑使用RestTemplate + Feign共存的方式……Spring Cloud官方也承认,无论Fegin怎么改进,其灵活性也无法比得上RestTemplate!但是,这么做之前请务必慎重,记住,共存带来的往往不是相得益彰,反而是歧义、错乱以及额外的学习成本、理解成本。

配套代码

GitHub:https://github.com/eacdy/spring-cloud-study/tree/master/2018-Finchley/microservice-consumer-movie-feign

Gitee:https://gitee.com/itmuch/spring-cloud-study/tree/master/2018-Finchley/microservice-consumer-movie-feign

相关文章

 

分享到:
评论

相关推荐

    spring-cloud-openfeign-core-3.1.1-API文档-中英对照版.zip

    包含翻译后的API文档:spring-cloud-openfeign-core-3.1.1-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.springframework.cloud:spring-cloud-openfeign-core:3.1.1; 标签:cloud、spring、...

    spring-cloud-openfeign-core-3.1.1-API文档-中文版.zip

    包含翻译后的API文档:spring-cloud-openfeign-core-3.1.1-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.cloud:spring-cloud-openfeign-core:3.1.1; 标签:cloud、spring、openfeign、core...

    feign-form-spring-3.8.0-API文档-中文版.zip

    包含翻译后的API文档:feign-form-spring-3.8.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:io.github.openfeign.form:feign-form-spring:3.8.0; 标签:openfeign、spring、github、form、feign、jar包、java...

    spring-cloud-openfeign-core-3.0.4-API文档-中文版.zip

    包含翻译后的API文档:spring-cloud-openfeign-core-3.0.4-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.cloud:spring-cloud-openfeign-core:3.0.4; 标签:springframework、cloud、spring...

    springcloud-feign.zip

    springcloud整合openFeign,包括feign的基本使用、传参、指定特定的服务器、负载均衡等使用方法。...springcloud-feign-api springcloud-feign-consumer springcloud-feign-provider springcloud-feign-providerV2

    springcloud-eureka-feign-mybatis-seata.zip

    在"springcloud-eureka-feign-mybatis-seata"项目中,开发者可以学习如何整合这些技术来创建一个完整的分布式事务示例。通过Eureka,服务能够被发现和调用;借助Feign,跨服务调用变得简单;MyBatis负责与数据库交互...

    spring-cloud-user-feign.zip

    在本项目"spring-cloud-user-feign.zip"中,我们探讨的是如何在Spring Cloud框架下实现服务间的调用,特别是利用Feign客户端进行微服务通信。这个压缩包包含了四个关键组件,分别是: 1. spring-cloud-gateways:这...

    springcloud-app-parent是一个SpringCloud的练习实践项目

    【SpringCloud】springcloud-app-parent是一个SpringCloud的练习实践项目,集成了nacos,eureka, feign,springcloud-gateway,springcloud-config,rabbitmq,ka... (Springcloud app parent is a SpringCloud practice ...

    SpringCloud-2.0-order-Feign-8005.zip

    在本项目"SpringCloud-2.0-order-Feign-8005.zip"中,主要探讨了如何在Spring Cloud 2.0环境下利用Feign客户端实现服务间的调用,并达到与`@LoadBalanced`注解类似的效果,即负载均衡。Spring Cloud是基于Spring ...

    springcloud-ribbon-feign-hystrix-zuul-config

    在Spring Cloud框架中,"springcloud-ribbon-feign-hystrix-zuul-config"这个标题涉及到四个关键组件:Ribbon、Feign、Hystrix和Zuul,以及配置管理Config。这些组件都是构建分布式系统时常用的服务发现、客户端负载...

    springcloud-learning-master.zip

    本压缩包“springcloud-learning-master.zip”提供了一套完整的SpringCloud学习资料,包括Eureka、Ribbon、Nacos、SpringCloud以及Feign等多个组件的实践教程。 1. **Eureka**:Eureka是Spring Cloud Netflix项目的...

    springcloud-learning-master.zip springcloud学习合集

    本压缩包"springcloud-learning-master.zip"是一个关于SpringCloud学习的资源合集,包含了一系列的例子和教程,适合想要深入理解和掌握SpringCloud技术的开发者。 首先,我们要了解SpringCloud的基础概念。Spring...

    spring-cloud-hystrix-feign(注册中心、member、feign-order).zip

    然后,"SpringCloud-2.0-order-hystrix-feign-8012"展示了如何使用Feign和Hystrix进行服务间调用。Feign是一个声明式Web服务客户端,使得编写Web服务客户端就像编写Java接口一样简单。在Order服务中,我们可以定义一...

    springcloud2-hystrix-feign-zuul.zip

    标题 "springcloud2-hystrix-feign-zuul.zip" 提示了我们这是一组关于Spring Cloud 2的实现,具体涉及Hystrix、Feign和Zuul组件的实践项目。Spring Cloud 是一个用于构建分布式系统的服务发现、配置管理和微服务连接...

    spring-cloud-examples-master

    《Spring Cloud实战详解:基于spring-cloud-examples-master的深度解析》 在当今的软件开发领域,微服务架构已经成为主流趋势,而Spring Cloud作为Java生态中的微服务治理框架,深受开发者们的喜爱。本篇文章将深入...

    srping-cloud-alibaba-nacos-feign.zip

    《Spring Cloud Alibaba Nacos与Feign的整合应用详解》 在微服务架构中,服务间的通信是关键一环。Spring Cloud Alibaba提供了丰富的组件,其中包括Nacos作为服务注册与配置中心,以及Feign作为声明式服务调用工具...

    springcloud-feign-demo 代码,简单演示拦截器,包含全局拦截器 局部拦截器 带url过滤的拦截器

    springcloud-feign-demo 代码,简单演示拦截器,包含全局拦截器 局部拦截器 带url过滤的拦截器

    venus-cloud-feign-1.5.x.rar_cloud_feign_formery87_spring

    《Spring Cloud Feign 扩展详解——venus-cloud-feign-1.5.x 版本解析》 在分布式系统开发中,Spring Cloud Feign 是一个备受推崇的服务调用组件,它简化了服务间的通信,提供了声明式的接口调用方式。本文将深入...

Global site tag (gtag.js) - Google Analytics