上一篇分享了使用 Ribbon 进行服务的消费(调用),这一篇中我们分享一下使用 feign 的服务消费。
一、什么是 feign
首先,当然是要说说什么是 feign,为什么要用 feign 呢?
这段话里已经说明了 feign 是一个声明式的 web 服务客户端,它简化了我们编写 web 服务客户端的操作。并且它使用注解,具有可插拔、负载均衡、服务熔断等一系列便捷功能。
有人可能会问了,前一篇中我们使用 Ribbon 不也是能够进行服务的调用,并且也具备负载均衡功能嘛,为什么还要用 feign,是多此一举吗?答案当然是不,要不然谁会没事儿多搞个 feign 来浪费大家时间呢?
Ribbon 与 Feign 的关系?
而且 Feign 的使用比 Ribbon 更简单,只需要通过注解便可简单实现服务的消费。
总结
1 Feign 是一个 Http 客户端
2 支持 Feign 注解和 JAX-RS 注解
3 Feign 基于 Ribbon 实现,具有 Ribbon 的功能,包括负载均衡
4 Feign 具备 Hystrix 的服务熔断功能(服务熔断:防止由于服务调用时的网络问题或服务掉线而引发的一系列问题)
二、Feign 使用示例
2.1 创建项目
这里使用之前创建的 logistics-service 项目作为示例
2.2 添加依赖
在 pom.xml 中添加 feign 的依赖,并使用 maven 导入依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.3 添加 Feign 注解
在项目的启动类上添加 @EnableFeignClients 的注解
package com.jiangzhuolin.logisticsservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class LogisticsServiceApplication {
public static void main(String[] args) {
SpringApplication.run(LogisticsServiceApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
2.4 定义 Feign 接口
在 logistics-service 项目中定义一个接口来进行 feign 的服务消费定制。
package com.jiangzhuolin.logisticsservice.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(value = "user-service")
public interface ILogisticsService {
@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
String getUserInfo(@PathVariable(value = "id") long id);
}
- @FeignClient() 声明了这是一个 Feign 客户端,里面的 value = "user-service" 表示要调用的是 user-service 这个服务(在 application.yml 配置的 )。
- @RequestMapping 注意区分此处的 RequestMapping 用于指定要调用的对方服务的 URI,而不是对外提供的 URI。上面的代码表示要调用的是 user-service 服务的 /user/{id} 这个接口,其中 id 为 路径参数。
- getUserInfo() 方法里的参数表示传递给调用服务的接口(user service 服务)的参数,如此处表示调用 getUserInfo 方法传递的 id 将作为 user-service 服务的 /user/{id} 接口的一个路径参数被传递
2.5 修改 logistics 服务的 controller
将 LogisticsController 中的接口调用由原来的 Restemplate + Ribbon 改为 Feign。
package com.jiangzhuolin.logisticsservice.controller;
import com.jiangzhuolin.logisticsservice.service.ILogisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/logistics/")
public class LogisticsController {
@Autowired
private ILogisticsService logisticsService;
@RequestMapping(value = "/message")
public String message(long userId) {
String response = logisticsService.getUserInfo(userId);
return response;
}
}
- @Autowired 注入 ILogisticsService
- 在 Controller 方法中直接调用 ILogisticsService 中定义的 Feign 的调用方法。
2.6 启动项目并验证
直接在本地启动 logistics-service 项目,并验证接口调用。
调用 logistics-service 的接口调用 logistics-service 的接口,可以看到通过 logistics-service 服务的接口,我们拿到了 user-service 服务的数据,而这个过程中,我们只是加了几个注解,配置了几个参数即可。
总结
从上面的示例我们可以明显地看出,Feign 的作用就是为了极大的简化我们在微服务架构下的不同服务间调用。并且贴心地为我们解决了负载均衡与服务熔断的两个难点。