欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的使用

程序员文章站 2022-05-18 20:57:52
...

Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的使用

在Spring Cloud Netflix栈中,各个微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端。我们可以使用JDK原生的URLConnection、Apache的Http Client、Netty的异步HTTP Client, Spring的RestTemplate。但是,用起来最方便、最优雅的还是要属Feign了。

Feign简介
Feign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用Feign, 我们可以做到使用HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。比如:

@RestController
public class DeptController_Consumer {

    @Autowired
    DeptClientService clientService;  // 远程服务

   
    @RequestMapping(value = "/consumer/dept/add")
    public boolean add(Dept dept) {
        return clientService.add(dept);    //通过HTTP调用远程add服务接口
    }
    
    @RequestMapping(value = "/consumer/dept/get/{id}", method = RequestMethod.GET)
    public Dept get(@PathVariable("id") Long id) {
        return clientService.get(id);    //通过HTTP调用远程get服务接口
    }
    
    @RequestMapping(value = "/consumer/dept/list", method = RequestMethod.GET)
    public List<Dept> list() {
        return clientService.list();    //通过HTTP调用远程list服务接口
    }

}

以上就是使用feign进行远程方法调用,很像我们的controller调用service接口
开发者通过clientService.add(dept)…就能完成发送HTTP请求和解码HTTP返回结果并封装成对象的过程。

Feign的定义
为了让Feign知道在调用方法时应该向哪个地址发请求以及请求需要带哪些参数,我们需要定义一个接口:

@FeignClient(value = "MICROSERVICECLOUD-DEPT")
public interface DeptClientService {


    // 以下接口其实就是拿MICROSERVICECLOUD-DEPT服务提供者提供的接口(controller层提供的接口)
    // 我们将这些接口统一的放在一个自定义接口DeptClientService当中,
    // 接口上添加@FeignClient(value = "服务提供者微服务名称"),我们就可以做到使用HTTP请求远程服务时能与
    // 调用本地方法一样的编码体验(此自定义的接口里的所有方法,其实就是服务提供者远程提供的接口方法,
    // 我们要调用服务提供者提供的方法也就是接口,我们只需要将此DeptClientService接口对象 @Autowired到
    // 要调用的位置,类似于传统的controller层调用service层)
    // 开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求,
    // 这就是面向接口开发的魅力,就问你牛B吗?

    @RequestMapping(value = "/dept/add",method = RequestMethod.POST)
    public boolean add(@RequestBody Dept dept);

    @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
    public Dept get(@PathVariable("id") Long id);

    @RequestMapping(value = "/dept/list", method = RequestMethod.GET)
    public List<Dept> list();
}
接口其实就是拿MICROSERVICECLOUD-DEPT服务提供者提供的接口(controller层提供的接口)
    我们将这些接口统一的放在一个自定义接口类DeptClientService当中(一般我们将自定义接口类放在统一的api工程当中,方便复用),
    接口上添加@FeignClient(value = "服务提供者微服务名称"),我们就可以做到使用HTTP请求远程服务时能与
    调用本地方法一样的编码体验(此自定义的接口里的所有方法,其实就是服务提供者远程提供的接口方法,
    我们要调用服务提供者提供的方法也就是接口,我们只需要将此DeptClientService接口对象 @Autowired到
    要调用的位置,类似于传统的controller层调用service层)
    开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求,
    这就是面向接口开发的魅力,就问你牛B吗?

@FeignClient用于通知Feign组件对该接口进行代理(不需要编写接口实现),使用者可直接通过@Autowired注入。

@RequestMapping表示在调用该方法时需要向/…发送GET/POST/…请求。

@PathVariable与SpringMVC中对应注解含义相同。

以下就是feign使用案例,pom文件依赖就不展示了:
Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的使用
Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的使用
Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的使用
Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的使用
Spring Cloud Feign作为HTTP客户端调用远程HTTP服务的使用
Feign原理简述
1 Spring Cloud应用在启动时,程序会进行包扫描,扫描所有包下所有标有@FeignClient注解的接口,生成代理对象,并将这些接口注入到spring的IOC容器中

2 当定义的Feign中的接口被调用时,通过JDK的动态代理来生成RequestTemplate代理对象。
该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里

3 RequestTemplate再生成Request。

4 然后将Request交给client处理,这个client默认是JDK的HttpUrlConnection(也可以是HttpClient或Okhttp,需要配置)

5 最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡。

在本例中,我们将Feign与Eureka和Ribbon组合使用,@FeignClient(value = “MICROSERVICECLOUD-DEPT”)意为通知Feign在调用该接口方法时要向Eureka中查询名为MICROSERVICECLOUD-DEPT的服务,从而得到服务URL。

总结
通过Feign, 我们能把HTTP远程调用对开发者完全透明,得到与调用本地方法一致的编码体验。这一点与阿里Dubbo中暴露远程服务的方式类似,区别在于Dubbo是基于私有二进制协议,而Feign本质上还是个HTTP客户端。如果是在用Spring Cloud Netflix搭建微服务,那么Feign无疑是最佳选择。