Spring Cloud 服务消费(Feign)

在使用 RestTemplate 实现 Rest API 调用的时候,是通过拼接字符串的方式构造 URL,向具体服务实例发起 Http 请求。在定义 RestTemplate 的时候,还可以增加 @LoadBalanced 注解,在调用服务接口的时候,原来 host 部分是通过手动拼接ip和端口的,现在直接用 服务名 来写请求路径。在真正调用的时候,Spring Cloud 会将请求拦截下来,然后通过负载均衡器(如 Ribbon)选出节点,并替换服务名部分为具体的ip和端口,从而实现基于服务名的负载均衡调用,相关见 Spring Cloud 服务消费(Ribbon)

以上的方式可以实现负载均衡调用,但是由于每个调用都要拼接 URL,传递的参数也需要放在 URL 中,这样的开发体验是很不好的,比较低效且难以维护。可以使用 Feign 实现声明式 REST 调用

Feign 简介

Feign 是 Netflix 的一套的声明式服务调用客户端。它使得编写Web服务客户端变得更加简单。我们只需要通过创建接口并用注解来配置它即可。它具备可插拔的注解支持,包括Feign注解和JAX-RS注解。支持可插拔编码器和解码器。Spring Cloud 对 Feign 进行了增强,扩展了对Spring MVC 注解的支持,并整合了 Ribbon 和 Eureka 来提供均衡负载的 HTTP 客户端实现。

使用 Feign

我们利用之前的例子(见 Spring Cloud 服务消费(Ribbon)),eureka-server 作为服务注册中心、product-service 作为服务提供者,order-service-ribbon 是服务消费者。复制 order-service-ribbonorder-service-feign,在 order-service-feign 上去做一些更改

添加 Feign 的依赖

pom.xml
1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

修改启动类,添加 @EnableFeignClients 注解

OrderServiceFeignApplication.java
1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServiceFeignApplication {

public static void main(String[] args) {
SpringApplication.run(OrderServiceFeignApplication.class, args);
}
}

创建 Feign 接口,添加 @FeignClient 注解

ProductFeignClient
1
2
3
4
5
6
@FeignClient("product-service")
public interface ProductFeignClient {

@GetMapping("/product/{id}")
Product getProduct(@PathVariable Long id);
}

调用 Feign 接口

ProductController.java
1
2
3
4
5
6
7
8
9
10
11
12
@RestController
@Log4j2
public class ProductController {

@Autowired
private ProductFeignClient productFeignClient;

@GetMapping("/product/{id}")
public Product getProduct(@PathVariable Long id) {
return productFeignClient.getProduct(id);
}
}

启动 eureka-server、product-service:8071、product-service:8072、order-service-feign,访问 http://localhost:8081/product/1 可以查看结果


示例代码:demo