Feign定义
Feign是Spring Cloud Netiflix组件中的一个轻量级Restful的HTTP服务客户端,通过 接口 + 注解的方式发起 HTTP 请求调用。
Feign面向接口编程,而不是像 Java 中通过封装 HTTP 请求报文的方式直接调用,集成了Ribbon(负载均衡组件)和Hystrix(服务治理组件)。
Feign被应用在Spring Cloud 的解决方案中,是学习基于Spring Cloud 微服务架构不可或缺的重要组件。
Feign作用
Feign 主要是帮助我们方便进行Rest API服务间的调用,Feign最大的作用就是减少 HTTP 远程调用的复杂性。
Feign实现了像调用本地方法一样调用远程方法,无感知远程HTTP 请求,类似于Dubbo Consumer直接调用Provider的接口方法。
服务消费方拿到服务提供方的接⼝,然后像调⽤本地接⼝⽅法⼀样去调⽤,实际发出的是远程的请求。
Feign使得开发人员无需关注与远程的交互细节,将更多的注意力集中在具体的业务开发,被⼴泛应⽤在 Spring Cloud 的解决⽅案中。
Feign使用
在Spring Cloud中使用 Feign 非常简单,创建一个接口并在接口上添加一些注解,代码就完成了。
如下所示:
1.引入 feign 的依赖
<!-- 支持使用feign客户端 -->
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
2.开启Feign
通过@EnableFeignClients注解,开启Spring Cloud Feign的支持功能。
如下所示:
@MapperScan("com.mikechen.orderservice.mapper") @SpringBootApplication @EnableFeignClients //开启Feign的功能 public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
3.创建业务接口
添加@FeignClient接口,此接口是在Feign中调用微服务的核心接口,声明需要调用的服务。
如下所示:
@FeignClient("userservice") public interface UserClient { @GetMapping("/user/{id}") User findById(@PathVariable("id") Long id); }
详细的参数解释如下:
- 定义各参数绑定时:@PathVariable、@RequestParam、@RequestHeader等可以指定参数属 性;
- @FeignClient:注解通过name指定需要调用的微服务的名称,上面指定目标服务名称:userservice;
- @GetMappding 指定发起的请求方式:GET;
- @GetMappding 参数指定请求路径:/user/{id};
- 成员方法的返回值指定了 http 请求返回值的类型:User;
4.Feign调用接口
然后就可以在代码中通过调用该接口类的方法来发起 http 请求了。
如下所示:
@Service public class OrderService { @Autowired OrderMapper orderMapper; @Autowired private UserClient userClient; public Order queryOrderById(Long orderId) { // 1.查询订单 Order order = orderMapper.findById(orderId); // 2.利用feign发起http请求 User user = userClient.findById(orderId); // 3.封装user到Order order.setUser(user); // 4.返回 return order; } }
以上就使用了 Feign 客户端代替了 RestTemplate 来发起 http 请求。
Feign原理
通过上面的使用示例,我们知道了在启动类上标记 @EnableFeignClients 注解来开启feign的功能。
@MapperScan("com.mikechen.orderservice.mapper") @SpringBootApplication @EnableFeignClients //开启Feign的功能 public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
服务启动后会扫描 @FeignClient 注解标记的接口,然后根据扫描的注解信息为每个接口类生成feign客户端请求。
同时解析接口方法中的Spring MVC的相关注解,通过专门的注解解析器识别这些注解信息,以便后面可以正确的组装请求参数,使用 Ribbon 和 Eureka 获取到请求服务的真实地址等信息。
最后使用 http 相关组件进行执行调用。
其Feign大致工作流程图如下:
总的来说Feign 的源码实现过程如下:
1.首先通过@EnableFeignClients注解开启FeignClient 的功能,只有这个注解存在,才会在程序启动时开启对@FeignClient注解的包扫描;
2.根据Feign的规则实现接口,并在接口上面加上@FeignClient注解;
3.程序启动后会进行包扫描,扫描所有的@ FeignClient 的注解的类,并将这些信息注入IOC容器中;
4.当接口的方法被调用时,通过JDK的代理来生成具体的RequestTemplate模板对象;
5.根据RequestTemplate再生成Http请求的Request对象;
6.Request 对象交给Client去处理,其中Client的网络请求框架可以是HtpURLConnection、HttpClient等;
7.最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》