Spring Cloud Feign(声明式/模板化的HTTP客户端)

简介: 来源Feign使得 Java HTTP 客户端编写更方便。Feign 灵感来源于Retrofit、JAXRS-2.0和WebSocket。Feign 最初是为了降低统一绑定Denominator到 HTTP API 的复杂度,不区分是否支持 Restful。

来源

Feign使得 Java HTTP 客户端编写更方便。Feign 灵感来源于RetrofitJAXRS-2.0WebSocketFeign 最初是为了降低统一绑定DenominatorHTTP API 的复杂度,不区分是否支持 Restful

Retrofit是Square开发的一个AndroidJavaREST客户端库。
github地址:https://github.com/square/retrofit

JAX-RS(Java API for RESTful Web Services) 2.0 又称JSR 339 不仅定义了一套用于构建 RESTful 网络服务的 API,同时也通过增强客户端 API 功能简化了REST 客户端的构建过程。
github地址:https://github.com/eclipse-ee4j/jaxrs-api
WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。
协议说明:https://tools.ietf.org/html/rfc6455

Denominator是一个用于操作DNS云的可移植Java
github地址:https://github.com/Netflix/Denominator

简介

Spring Cloud Netflix 的微服务都是以 HTTP 接口的形式暴露的,
所以调用方式有:
JDK原生的URLConnection
Apache的Http Client
Netty的异步HTTP Client
Spring的RestTemplate
Feign
而 Feign 是一个使用起来更加方便的 HTTP 客戶端,使用起来就像是调用自身工程的方法,而感觉不到是调用远程方法。feign还支持可插拔的编码器和解码器,Spring在用的时候增加了对@requestMapping的处理,Feign 的目的是尽量的减少资源和代码来实现和HTTP API的连接。通过自定义的编码解码器以及错误处理,可以编写任何基于文本的HTTP API

github地址:https://github.com/OpenFeign/feign
在源码中可以看到子模块包括RibbonHystrix,所以feign是基于RibbonHystrix的声明式服务调用组件。Feign是一种声明式、模板化的HTTP客户端。

`

实现声明式REST客户端Feign

引入Spring Cloud Feign依赖以及相关依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

注:网上有的文章说引入的依赖是spring-cloud-starter-feign,其实官方不再推荐使用,推荐使用spring-cloud-starter-openfeign

在应用主类中通过@EnableFeignClients注解开启Feign功能,因为要注册服务,所以还要使用@EnableEurekaClient

@SpringBootApplication
@EnableFeignClients
@EnableEurekaClient
public class SpringcloudFeignApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringcloudFeignApplication.class, args);
    }
}

修改yml配置文件

server:
  port: 8088
eureka:
  client:
    service-url:
      defaultZone: http://localhost:9090/eureka
spring:
  application:
    name: springcloud-feign-client

重点:Feign声明式/模块化体现

接下来定义服务接口类
使用@FeignClient("springcloud-eureka-client")注解来绑定该接口对应springcloud-eureka-client服务

@Component
@FeignClient(name = "springcloud-eureka-client")
public interface Client {
    @GetMapping("/client")
    public String getInfo();
}

通过声明式的注解,提供一个供其它服务调用的 Client。
@FeignClient用于通知Feign组件对该接口进行代理(不需要编写接口实现),使用者可直接通过@Autowired注入
注:多个feignCLient类中@FeignClient注解中的name值不能重复,url可以重复
Spring Cloud应用在启动时,Feign会扫描标有@FeignClient注解的接口,生成代理,并注册到Spring容器中。生成代理时Feign会为每个接口方法创建一个RequetTemplate对象,该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里。

注意:绑定的接口服务必须是对应服务上存在的接口
例如我把接口名改为client123便会报如下错误

image.png

也就是找不到对应的接口服务,所绑定的springcloud-eureka-client没有client123接口

这是springcloud-eureka-client服务中的client接口

@RestController
public class DiscoveryController {
    @Autowired
    private DiscoveryClient discoveryClient;
    @Value("${server.port}")
    private String ip;

    @GetMapping("/client")
    public String client() {
        String services = "调用的服务是: " + discoveryClient.getServices()+" 对应的端口号 :"+ip;
        System.out.println("调用的服务是: " + discoveryClient.getServices()+" 对应的端口号 :"+ip);
        return services;
    }
}

调用上面定义的接口

@RestController
public class FeignClientController {
    @Autowired
    Client client;
    @GetMapping("/info")
    public String getInfo(){
        return client.getInfo();
    };
}

这里的接口名就任意取了,这里主要是获取绑定服务的接口的信息。

整体项目结构

Eureka服务端 端口号是9090
Eureka客户端 端口号是8082 服务名springcloud-eureka-client
feign消费者客户端 端口号是8088
(如需测试负载均衡的可以再启动一个端口号为8081的服务,服务名同样是springcloud-eureka-client)

启动服务进行测试

先启动服务端再启动客户端,客户端启动顺序没要求
访问http://localhost:9090服务注册中心

image.png

在服务注册中心可以看到,服务提供者和消费者都注册好了

访问feign定义的接口/infohttp://localhost:8088/info

image.png

测试负载均衡

服务列表

image.png

访问http://localhost:8088/info
image.png

刷新下,再次访问
image.png

实现了与Ribbon相同的负载均衡功能

实现Feign熔断

需要先写一个调用延迟或失败时调用的类

@Component
public class FailClass implements Client{
    @Override
    public String getInfo() {
        return "服务中断连接,请联系管理员";
    }
}

需要实现自定义服务接口的方法,以至于显示对应服务的对应接口调用失败的返回信息
然后在自定义服务接口中添加fallback异常处理回调。

@Component
@FeignClient(name = "springcloud-eureka-client",fallback = FailClass.class)
public interface Client {
    @GetMapping("/client")
    public String getInfo();
}

还需要在yml配置文件中开启熔断,默认为false

feign:
  hystrix:
    enabled: true

关闭两个springcloud-eureka-client服务后访问http://localhost:8088/info会显示

image.png

总结:

其实通过Feign封装了HTTP调用服务方法,使得客户端像调用本地方法那样直接调用方法,Feign本质上是个HTTP客户端
Feign继承特性用起来确实很方便,但是也带来一个问题,就是服务提供者和服务消费者的耦合度太高,此时如果服务提供者修改了一个接口的定义,服务消费者可能也得跟着变化,进而带来很多未知的工作量,如果通过此方法来实现接口共享的话,建议严格遵守面向对象的开闭原则,尽可能低做好前后版本兼容,防止因为版本原因造成接口定义的不一致。

推荐文章
Feign相关参数配置:https://blog.csdn.net/u012702547/article/details/78327668?locationNum=10&fps=1
Feign源码分析:https://blog.csdn.net/forezp/article/details/73480304

目录
相关文章
|
20天前
|
消息中间件 监控 Java
如何将Spring Boot + RabbitMQ应用程序部署到Pivotal Cloud Foundry (PCF)
如何将Spring Boot + RabbitMQ应用程序部署到Pivotal Cloud Foundry (PCF)
31 6
|
20天前
|
Java 关系型数据库 MySQL
如何将Spring Boot + MySQL应用程序部署到Pivotal Cloud Foundry (PCF)
如何将Spring Boot + MySQL应用程序部署到Pivotal Cloud Foundry (PCF)
39 5
|
20天前
|
缓存 监控 Java
如何将Spring Boot应用程序部署到Pivotal Cloud Foundry (PCF)
如何将Spring Boot应用程序部署到Pivotal Cloud Foundry (PCF)
31 5
|
2月前
|
JSON Java 数据格式
【微服务】SpringCloud之Feign远程调用
本文介绍了使用Feign作为HTTP客户端替代RestTemplate进行远程调用的优势及具体使用方法。Feign通过声明式接口简化了HTTP请求的发送,提高了代码的可读性和维护性。文章详细描述了Feign的搭建步骤,包括引入依赖、添加注解、编写FeignClient接口和调用代码,并提供了自定义配置的示例,如修改日志级别等。
127 1
|
3月前
|
负载均衡 Java Nacos
SpringCloud基础2——Nacos配置、Feign、Gateway
nacos配置管理、Feign远程调用、Gateway服务网关
SpringCloud基础2——Nacos配置、Feign、Gateway
|
3月前
|
前端开发 API 微服务
SpringCloud微服务之间使用Feign调用不通情况举例
SpringCloud微服务之间使用Feign调用不通情况举例
660 2
|
5月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
15051 33
|
3月前
|
Java API 开发者
【已解决】Spring Cloud Feign 上传文件,提示:the request was rejected because no multipart boundary was found的问题
【已解决】Spring Cloud Feign 上传文件,提示:the request was rejected because no multipart boundary was found的问题
664 0
|
5月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
580 15
|
5月前
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
126 3

热门文章

最新文章

下一篇
DataWorks