在实践的过程中,我们会发现在微服务架构中实现客户端负载均衡的服务调用技术Spring Cloud Ribbon《SpringCloud开发学习总结(四)—— 客户端负载均衡Ribbon》 和Spring Cloud Hystrix熔断器保护机制 《SpringCloud开发学习总结(五)—— 服务容错保护Hystrix》往往是同时出现的。既然如此,那么是否有更高层次的封装来整合这两个基础工具以简化开发呢?本文我们介绍的SpringCloud Feign就是这样一个工具,它基于Netflix Feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供这两者的强大功能之外,它还提供了一种声明式Web服务客户端定义方式。
我们在使用Spring Cloud Ribbon时,通常都会利用它对RestTemplate①的请求拦截来实现对依赖服务的接口调用,而RestTemplate已经实现了对HTTP请求的封装处理,形成了一套模板化的调用方法。在之前的例子中,只是简单介绍了RestTemplate调用的实现,但是在实际开发中,由于对服务依赖的调用可能不止于一处,往往一个接口会被多处调用,所以我们通常都会针对各个微服务自行封装一些客户端类来包装这些依赖服务的调用。这个时候我们会发现,由于RestTemplate的封装,几乎每一个调用都是简单的模板化内容。综上所述,Spring Cloud Feign在此基础上做了进一步的封装,由它来帮助我们定义和实现依赖服务接口的定义。在Spring Cloud Feign的实现下,我们只需创建一个接口并用注解的方式来配置它,即可完成对服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。Spring Cloud Feign 具备可插拔的注解支持,包括Feign注解和JAX-RS注解。同时,为了适应Spring的广大用户,它在Netflix Feign的基础上扩展了对Spring MVC的注解支持。对于习惯Spring MVC的开发者大大减少了学习使用它的成本。另外,对于Feign自身的一些主要组件,比如编码器和解码器等②,它也以可插拔的方式提供,在有需求的时候我们可以方便地扩展和替换它们。
快速入门
下面我们通过一个简单的示例来展现Spring Cloud Feign在服务客户端定义上所带来的便利,我们会通过Spring Cloud Feign提供的声明式服务绑定功能来实现对该服务接口的调用。
- 首先,创建一个Spring Boot基础工程,取名为feign-consumer,并在pom.xml中引入:
- 创建应用主类ConsumerApplication,并通过@EnableFeignClients注解开启Spring Cloud Feign的支持功能。
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class consumeApplication { public static void main(String[] args) {
SpringApplication.run(consumeApplication.class, args);
}
}
- 定义HelloService接口,通过@FeignClient注解指定服务名来绑定服务,然后再使用Spring MVC的注解来绑定具体该服务提供的REST接口。
@FeignClient("hello-service")
public interface HelloService { @RequestMapping(value="/hello")
String hello(); }
- 接着,创建一个ConsumerController来实现对Feign客户端的调用。使用@Autowired直接注入上面定义的HelloService实例,并在helloConsumer函数中调用这个绑定了hello-service服务接口的客户端来向该服务发起/hello接口的调用。
@RestController
public class ConsumeController { @Autowired
HelloService helloService; @RequestMapping(value="/feign-consumer",method=RequestMethod.GET)
public String helloConsumer(){
return helloService.hello();
} }
- 最后,同Ribbon实现的服务消费者一样,需要在application.properties中指定服务注册中心,并定义自身的服务名为feign-consumer
server.port = 8092 spring.application.name=feign-consumer
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
经验证,发送请求http://localhost:8092/feign-consumer,可以得到如之前Ribbon实现时一样的效果,依然是Ribbon维护了针对HELLO-SERVICE的服务列表信息,并且通过轮询实现了客户端负载均衡。而与Ribbon不同的是,通过Feign我们只需要定义服务绑定接口,以声明式的方法,优雅而简单的实现了服务调用。
至此,简单的SpringCloud+Feign项目搭建完成!