🌥️SpringCloud实战-声明式HTTP客户端调用之OpenFeign
|字数总计:1.3k|阅读时长:5分钟|阅读量:|
前面我们使用Ribbon
实现了客户端调用的负载均衡。但我们的调用还是使用的RestTemplate
:
1 2 3 4 5 6 7
| @Autowired private RestTemplate restTemplate;
@GetMapping("/consumer/{id}") public String consume(@PathVariable String id) { return restTemplate.getForObject("http://eureka-client-service-provider/provider?id=" + id, String.class); }
|
这样的做法有两个不好的地方。一个是当URL
中的参数过多时难以进行拼接维护;另一个是我们还是能够很明显的知道我们在发送HTTP
请求。我们期望能够像调用本地方法一样去调用远程服务,不用关心URL
的参数拼接和HTTP
请求的发送。
Feign
简介
Feign
是一个声明式HTTP
客户端,我们只需按照一定的规则定义好接口,它就能帮助我们完成HTTP
的调用。Spring Cloud
对Feign
进行了增强,使其支持了Spring MVC
注解,同时整合了Ribbon
和Eureka
,让微服务间的调用更加方便。
使用Feign
调用远程服务
在IDEA
中创建一个名为openfeign
的maven
工程,然后在pom.xml
中引入以下依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <properties> <spring.boot.version>2.2.0.RELEASE</spring.boot.version> <spring.cloud.version>Hoxton.SR1</spring.cloud.version> </properties>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring.cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies>
|
在src/main/resources
目录下创建application.yml
配置文件,并添加以下配置项:
1 2 3 4 5 6 7 8 9
| server: port: 9004 spring: application: name: openfeign-service-consumer eureka: client: service-url: defaultZone: http://localhost:520/eureka/,http://localhost:521/eureka/
|
编写启动类OpenFeignApplication
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.sunchaser.sparrow.microservice.springcloud.openfeign;
import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication @EnableFeignClients public class OpenFeignApplication { public static void main(String[] args) { new SpringApplicationBuilder(OpenFeignApplication.class) .web(WebApplicationType.SERVLET) .run(args); } }
|
使用org.springframework.cloud.openfeign.EnableFeignClients
注解开启对feign
客户端的扫描。
下面我们就来写一个feign
客户端来完成微服务间的调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.sunchaser.sparrow.microservice.springcloud.openfeign.clients;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(url = "http://127.0.0.1:9000", name = "ProviderFeignClient") public interface ProviderFeignClient { @GetMapping("/provider") String provide(@RequestParam(value = "id") String id); }
|
使用@FeignClient
注解声明该接口是一个feign
客户端从而被@EnableFeignClients
注解扫描到,指定url
为服务提供方的地址http://127.0.0.1:9000
(提前启动好了服务提供者eureka-client-service-provider
),指定name
为任意唯一id
(当前接口类名)。
然后我们就可以像定义Spring MVC
中的Controller
那样定义我们的接口方法。使用@GetMapping("/provider")
定义请求方式和请求路径,使用@RequestParam(value = "id")
定义请求参数。
接下来我们就可以使用feign
客户端了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package com.sunchaser.sparrow.microservice.springcloud.openfeign.controller;
import com.sunchaser.sparrow.microservice.springcloud.openfeign.clients.ProviderFeignClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController;
@RestController public class OpenFeignConsumerController { @Autowired private ProviderFeignClient providerFeignClient;
@GetMapping("/consumer/{id}") public String consume(@PathVariable String id) { return providerFeignClient.provide(id); } }
|
我们像调用本地方法一样调用了远程服务。发送GET
请求:GET
http://localhost:9004/consumer/1
,可看到浏览器输出为provide:1
。
调用注册中心Eureka
上的服务提供者
上面的调用我们是通过@FeignClient
注解的url
属性指定了服务提供者的地址。这种情况适用于服务提供者为第三方提供的REST API
,无法注册到内部的注册中心上。
对于服务注册中心上的服务提供者,我们只需要指定name
属性为服务提供者的名称即可进行调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.sunchaser.sparrow.microservice.springcloud.openfeign.clients;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "eureka-client-service-provider") public interface ProviderFeignClient { @GetMapping("/provider") String provide(@RequestParam(value = "id") String id); }
|
负载均衡器Ribbon
会将eureka-client-service-provider
解析成Eureka Server
服务注册表中的服务地址进行负载均衡调用。
重启openfein
服务。重复发送GET
请求:GET
http://localhost:9004/consumer/1
,可看到两个服务提供者实例控制台上均有相关日志输出。
至此,我们使用feign
完成了服务间的调用,同时还实现了客户端的负载均衡。