spring cloud feign学习一:快速入门
Feign是什么?官网的一段话。
Feign is a declarative(声明式) web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable(可插拔) annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable encoders and decoders. Spring Cloud adds support for Spring MVC annotations and for using the same HttpMessageConverters used by default in Spring Web. Spring Cloud integrates(集成) Ribbon and Eureka to provide a load balanced http client when using Feign.
通过对spring cloud ribbon
和spring cloud hystrix
的介绍,我们已经掌握了开发微服务应用时的两个重磅武器,学会了如何在微服务架构中实现客户端负载均衡的服务调用以及如何通过断路器来保护我们的微服务应用。这二个组件都被广泛地应用在各个微服务实现中,不仅包括我们自身的业务类微服务,也包括一些基础设施类微服务(比如网关)。此外,在实践中,我们发现几乎对这二个框架的使用几乎都是同时出现的。既然如此,那么是否有更高层次的封装来整合这二个基础工具以简化开发呢?spring cloud feign
就是一个这样的工具。它基于Netfix Feign
实现,整合了spring cloud Ribbon
和spring cloud Hystrix
,除了提供这二者的强大功能之外,它还提供了一种生命式的web服务客户端定义方式。
我们在使用spring cloud ribbon
时,通常会利用它对rersttemplate
的请求拦截来实现对依赖服务的接口调用,而RestTemplate
已经实现了对http请求的封装处理,形成了一套模版花的调用方法。之前已经介绍了RestTemplate
调用的实现,但是在实际开发中,由于对服务依赖的调用可能不止于一处,往往一个接口会被多处调用,所以我们通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。这个时候我们发现,由于RestTemplate
的封装,几乎每一个调用都是简单的模版化内容。
综合上述所说,spring cloud feign
在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在spring cloud feign
的实现下,我们只需创建一个接口并调用注解的方式来配置它,即可完成对服务提供方的接口绑定,简化了使用spring cloud ribbon
时自动封装服务调用客户端的开发量。spring cloud feign
具备可插拔的注解支持,包括feign
注解和JAX-RS
注解。同时,为了适应Spring的广大用户,它在Netfix Feign
的基础上扩展了spring mvc
的注解支持,这对于习惯spring mvc
的开发者来说,无疑是个好消息,因为这样可以大大减少学习使用它的成本。另外,对于feign
自身的一些主要组件,比如说编码器和解码器等,它也以可插拔的方式提高,在有需要的时候我们可以方便地扩展和替换它们。
快速入门
- 创建
pay-service
服务,加入依赖,与之前的模块不一样的就是加入了spring-cloud-starter-feign
依赖,
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
</dependencies>
- 创建主体应用类,并在主体应用类上加上注解
@EnableFeignClients
:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class PayApplication {
public static void main(String[] args) {
SpringApplication.run(PayApplication.class,args);
}
}
- 定义
UserService
接口,通过@FeignClient("user-service")
注解指定服务名来绑定服务,然后在使用Spring mvc
的注解绑定具体的user-service
服务中提供的rest接口。
@FeignClient("user-service")
public interface UserService {
@RequestMapping(value = "/user/index",method = RequestMethod.GET)
String index();
@RequestMapping(value = "/user/hello",method = RequestMethod.GET)
String hello();
}
这里,这里的服务名不区分大小写,所以user-service
和USER_SERVICE
都可以的。另外,在Camden.SR7
版本中,原本的serviceId
属性已经被废弃了,若要写属性名,可以使用name
和value
。
- 接着,创建一个
PayController
来实现对feign客户端的调用,使用@Autowired
注解直接注入上面定义的UserService
实例,并在相应的方法中调用这个绑定了user-service
服务接口的客户端来向改服务发起接口的定义。
@RestController
@RequestMapping("/pay")
public class PayController {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
UserService userService;
@RequestMapping("/index")
public String index(){
return userService.index();
}
@RequestMapping("/hello")
public String hello(){
return userService.hello();
}
}
- 最后,同
ribbon
实现的服务消费一样,需要在application.yml
中指定服务注册中心,
spring:
application:
name: pay-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
instance:
instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
server:
port: 7070
- 测试验证
Ribbon
客户端负载均衡,同时启动服务注册和user-servcei
,user-service
启动了二个实例,然后启动pay-service
,
发送多个请求http://192.168.5.3:7070/pay/index
,发现二个user-service都能在控制台打印日志,我们看到了feign实现的消费者,依然是利用了Ribbon维护了user-service的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign我们只需要定义服务绑定接口,以声明式的方法,优雅而简单的实现了服务调用。
注意:
我们知道为了适应Spring的广大用户,它在Netfix Feign的基础上扩展了spring mvc的注解支持,但是springmvc4.0出现的一系列注解比如@GetMapping,@PostMapping,@PutMapping等等是Feign是不支持的,比如在pay项目中定义的UserService接口,如果在
@FeignClient(value = "user-service")
public interface UserService {
// @RequestMapping(value = "/user/index",method = RequestMethod.GET)
@GetMapping("/user/index")
String index();
...
在启动的时候就会抛出如下的异常
当然这些所谓的坑在开发阶段便会发现。
参考资料
Declarative REST Client: Feign
代码地址
代码地址