Feign声明式服务调用

技术需求点:

在SpringCloud部署的微服务系统中,消费者通过Feign组件调用提供者的微服务。

一.Feign简介

在前文SpringCloud+SpringBoot搭建服务注册与调用平台中,我们使用了Ribbon客户端实现了微服务之间的调用,Ribbon本身集成了负载均衡的功能,但是Ribbon有一个使用不便的地方:每次使用需要手动拼接请求的url,还要对返回的结果进行格式化处理。为了解决这个不便,SpringCloud提供了一个声明式的调用组件:Feign,它可以帮助我们便捷的调用注册在注册中心的微服务。

Feign是一种声明式调用组件,提供了一种基于接口的编程方式,我们只要声明接口并配置注解,SpringCloud会根据配置以Rest风格的方式从其它微服务系统中调用方法并获取数据。

  • 主要有以下几个优点:
    (1)可插拔的注解支持,包括Feign注解和JAX-RS注解;
    (2)支持可插拔的HTTP编码器和解码器;
    (3)支持Hystrix和它的Fallback;
    (4)支持Ribbon的负载均衡,如果某个微服务id下有两个端口提供2个同样的服务,会采用轮询机制调用;
    (5)支持HTTP请求和相应的压缩。
    https://segmentfault.com/a/1190000019685780?utm_source=tag-newest

二.工程搭建

在之前的文章中,我们已经搭建好了基于Springcloud + SpringBoot的工程结构:springcloud-eureka-server、springcloud-eureka-provider、springcloud-eureka-consumer等角色,这次只需要在springcloud-eureka-provider中将Ribbon组件调用的方式改成Feign即可。

1.pom文件中添加Feign依赖

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

我之前使用的版本:Spring Boot版本:1.5.3.RELEASE,Spring Cloud版本:Dalston.SR5。
添加feign的pom依赖之后,发现找不到用于负载均衡的LoadBalancedRetryFactory的包,上网查资料发现是SprongBoot和SpringCloud的版本问题,不是所有SpringBoot和SpringCloud的包都是兼容的,两者的版本必须匹配使用,官网上两者匹配的版本如下:


image.png

因此,我们项目中SpringBoot版本改为用:2.0.3.RELEASE,SpringCloud的版本改为用:Finchley.RELEASE,改动代码如下:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
    </parent>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

2.目录结构


image.png

3.创建UserFeignService接口
Feign只需要写一个接口,在接口配置好需要调用的微服务id,并声明接口即可。如代码所示,使用注解@FeignClient,"eureka-provider"是提供者的serviceid,在整个微服务系统中是唯一的,表明该接口将调用eureka-provider的服务。方法名称和返回类型直接copy被调用服务的方法即可。

//开启feign客户端,eureka-provider-user微服务的serviceid(唯一)
@FeignClient("eureka-provider")
public interface UserFeignService {
    @RequestMapping("/user")
    public List<User> getUsers();
}

@RequestMapping要写完整路径。我们这里路径比较简单,直接是"/user",如果原服务的路径是下面这种,就需要写成"/provider/user"


image.png

4.修改启动类
启动类上添加@EnableFeignClients开启Feign客户端。

@EnableFeignClients//开启Feign客户端
@EnableEurekaClient//开启Eureka客户端
@SpringBootApplication
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class,args);
    }
}

三.测试结果

依次启动springcloud-eureka-server(集群)、springcloud-eureka-provider、springcloud-eureka-consumer服务,启动成功后,查看控制台http://192.168.33.100:8761


image.png

输入http://127.0.0.1:9091/consumer,看到下列返回说明调用成功!

image.png

四.扩展

Feign还有另外一种继承与实现的使用方式,大概做法是抽离出一个公共API项目,写一个接口让消费者继承,实现方法在提供者中实现,调用该公共接口的方法即可。

这种做法的好处是创建了独立的api项目,可以很方便的实现接口定义和依赖共享,不用再复制粘贴接口,但弊端是增加了服务提供者和消费者之间的耦合,如果服务提供者修改了一个接口定义,消费者也得跟着变,进而带来一些坑。

有兴趣的同学可以参考:https://www.jianshu.com/p/ff79509b0962


后记

由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容