概述
Spring Cloud Consul 提供的 spring-cloud-consul-discovery
组件,基于 Spring Cloud 的编程模型,接入 Consul 作为注册中心,实现服务的注册与发现。
使用案例
案例代码对象仓库:
- 服务提供者:consul-discovery-user-provider
- 服务消费者:consul-discovery-user-consumer
项目搭建
Maven依赖
在 pom.xml 文件中,主要引入 Spring Cloud Consul Discovery 相关依赖。代码如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 把 Consul 作为注册中心,并实现对其的自动配置 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- 通过它提供健康检查的接口给 Consul -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
-
引入 spring-cloud-starter-consul-discovery 依赖,将 Consul 作为注册中心,并实现对它的自动配置。
-
引入 spring-boot-starter-actuator 依赖, 通过它提供健康检查的接口。
配置文件
创建 application.yml
配置文件,添加 Consul Discovery 配置项。配置如下:
server:
port: 8086
servlet:
context-path: /
spring:
# Spring Cloud Consul 通用配置项,{@link ConsulProperties}
cloud:
consul:
host: 172.24.29.120 #consul agent client 主机名字,默认是localhost
port: 8500
enabled: true #是否启用spring cloud consul,默认true
# Spring Cloud Consul Discovery 配置项,{@link ConsulDiscoveryProperties}
discovery:
register: true # 作为服务注册到Consul中,默认true
enabled: true # 是否启用服务发现,默认true
registerHealthCheck: true #是否启用服务健康检查,默认true
instance-id: ${spring.application.name}:${server.port}
prefer-ip-address: true
- spring.cloud.consul 配置项,设置 Consul 客户端的配置,对应 ConsulProperties 配置类。
- spring.cloud.consul.discovery 配置项,设置 Consul Discovery 配置项,对应 ConsulDiscoveryProperties 配置类。
服务提供者
创建UserController类提供HTTP 接口,代码如下:
@RequestMapping("/user")
@RestController
public class UserController {
@RestController
static class TestController {
@GetMapping("/query")
public String echo(String name) {
return "provider:" + name;
}
}
}
创建 ConsulProviderApplication类,创建应用启动类。代码如下:
@EnableDiscoveryClient
@SpringBootApplication
public class ConsulProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ConsulProviderApplication.class);
}
}
@EnableDiscoveryClient
注解,开启Spring Cloud
的服务发现功能。但是从 Spring Cloud Edgware 版本开始,已经不需要添加该注解,只需要引入服务发现组件,就会自动开启服务发现的功能。例如,我们这里已经引入了spring-cloud-starter-consul-discovery
依赖,就不用再添加这个注解了。
服务消费者
创建UserConsumerController类提供HTTP 接口,代码如下:
@Slf4j
@RequestMapping("/user")
@RestController
public class UserConsumerController {
@Autowired
DiscoveryClient discoveryClient;
@Autowired
private RestTemplate restTemplate;
//用于调用服务提供者的 /user/query 接口
@GetMapping("/consumer2")
public String consumer2(String name) {
//通过服务发现组件获取服务实例
List<ServiceInstance> instances = discoveryClient.getInstances("discovery-user-provider");
if(instances == null || instances.size() == 0){
throw new IllegalStateException("获取不到实例");
}
//通过服务实例 ServiceInstance 对象,拼接请求的目标 URL,使用 RestTemplate 发起 HTTP 调用。
String targetUrl = instances.get(0).getUri() + "user/query?name=" + name;
String response = restTemplate.getForObject(targetUrl, String.class);
return "consumer:" + response;
}
}
在 Spring Cloud Common 项目中,定义了 DiscoveryClient 接口,作为通用的服务发现客户端,提供查询服务列表的 API 方法。如果要集成到 Spring Cloud 体系的服务发现组件,需要提供对应的 DiscoveryClient 实现类。
- Spring Cloud Alibaba Nacos Discovery 提供了 NacosDiscoveryClient 实现。
- Spring Cloud Consul Discovery 提供了 ConsulDiscoveryClient 实现。
如此,所有需要使用到的地方,只需要获取到 DiscoveryClient 客户端,而无需关注具体实现,保证其通用性。
创建 ConsulConsumerApplication类,创建应用启动类。代码如下:
@EnableFeignClients //@EnableDiscoveryClient 注解,已经无需添加,原因在上面已经解释过
@SpringBootApplication
public class ConsulConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsulConsumerApplication.class);
}
//RestTemplate 是 Spring 提供的 HTTP 调用模板工具类,可以方便我们稍后调用服务提供者的 HTTP API。
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
}
测试
分别启动服务提供者和服务消费者,启动完成后,我们可以在 Consul 运维界面,看到该服务消费者。如下图所示:
注意
:服务消费者和服务提供是一种角色的概念,本质都是一种服务,都是可以注册自己到注册中心的。
访问服务消费者接口如下:
curl http://127.0.0.1:8200/user/consumer2?name=unite
返回结果为 " consumer:provider:unite "。说明调用远程服务成功。
Openfeign实现远程调用
Maven依赖
在服务消费者项目中pom.xml
文件加入openfeign
组件依赖。如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
定义FeignClient接口
在服务消费者创建UserFeignClient接口。代码如下:
//FeignClient注解设置服务提供者名字,在consul注册中心注册的服务名字
@FeignClient(name = "discovery-user-provider")
public interface UserFeignClient {
//定义服务提供者接口
@GetMapping("/user/query")
String echo(@RequestParam("name") String name);
}
服务消费者调用
在服务消费者应用中,UserConsumerController增加接口通过openFeign远程调用。代码如下:
@Slf4j
@RequestMapping("/user")
@RestController
public class UserConsumerController {
@Autowired
UserFeignClient userFeignClient;
@GetMapping("/consumer")
public String consumer(String name) {
String response = userFeignClient.echo(name);
return "consumer:" + response;
}
}
测试
访问服务消费者接口如下:
curl http://127.0.0.1:8200/user/consumer?name=unite
返回结果为 " consumer:provider:unite "。说明调用远程服务成功。
总结
通过对比发现,两种方式都能实现远程调用。而OpenFeign
封装复杂RPC
调用逻辑,实现远程调用。