xyZGHio

本是青灯不归客,却因浊酒恋风尘

0%

SpringCloud下基于Consul的服务注册与发现实践

Consul作为一款基于Go语言开发的开源工具,其可用于分布式系统的服务发现与配置

abstract.png

配置Consul

通过Docker先建立一个Consul服务

1
2
3
4
5
6
7
# 拉取镜像
docker pull consul:1.10

# 创建Consul容器
docker run -d -p 8500:8500 \
--name Consul-Service \
consul:1.10

然后,通过查看Consul的Web管理页面进行验证。 打开 http://localhost:8500 ,效果如下,符合预期

figure 1.jpeg

搭建服务提供者

POM依赖

这里我们建立一个SpringBoot项目——payment,作为服务的提供者。对于Consul作为注册中心的场景,在SpringCloud直接使用spring-cloud-starter-consul-discovery依赖即可

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
<dependencyManagement>
<dependencies>

<!--Spring Boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<!--Spring Cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>

</dependencies>
</dependencyManagement>

<dependencies>

<!-- Consul -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

</dependencies>

配置文件

配置文件在spring.cloud.consul配置项下指定Consul服务地址信息即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 通用配置
spring:
application:
name: payment
profiles:
active: payment4

---
# payment服务实例4配置
spring:
profiles: payment4
cloud:
consul:
# Consul 地址信息
host: 127.0.0.1
port: 8500
discovery:
# 服务名
service-name: ${spring.application.name}

server:
port: 8004

Java实现

简便起见,这里我们直接提供了一个Controller,用于测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController
@RequestMapping("pay")
public class PaymentController {

@Value("${server.port}")
private String serverPort;

@GetMapping("/hello")
public String hello(@RequestParam String name) {
String msg = "[Payment Service-"+ serverPort +"]: " + name;
return msg;
}

}

然后在启动类上添加 @EnableDiscoveryClient 注解即可

1
2
3
4
5
6
7
8
9
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class PaymentApplication {
public static void main(String[] args) {
SpringApplication.run(PaymentApplication.class, args);
}
}

搭建服务消费者

配置文件

类似地,我们还建立一个SpringBoot项目——order,作为服务消费者。由于其POM依赖与服务提供者的POM依赖并无二致。故这里不再赘述,直接复制即可。配置文件同理,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
spring:
application:
name: order
profiles:
active: order3

---
# order服务实例3配置
spring:
profiles: order3
cloud:
consul:
# Consul 地址信息
host: 127.0.0.1
port: 8500
discovery:
# 服务名
service-name: ${spring.application.name}

server:
port: 82

Java实现

首先声明创建RestTemplate实例。一个是普通的RestTemplate实例,一个则是添加了 @LoadBalanced 注解的RestTemplate实例。前者可进行基于IP、Port服务调用;后者由于添加了 @LoadBalanced 注解,其一方面可进行基于服务名的服务调用,另一方面支持负载均衡

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
@Configuration
public class RestTemplateConfig {

/**
* 普通的restTemplate实例, 可利用IP、Port调用服务
* @return
*/
@Bean
public RestTemplate restTemplate1() {
return new RestTemplate();
}

/**
* @LoadBalanced 注解作用:
* 1. 基于服务名调用的restTemplate实例
* 2. 支持负载均衡
* @return
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate2() {
return new RestTemplate();
}

}

然后通过Controller调用Payment服务接口。下面展现了 传统地基于IP、Port信息 和 基于服务名 两种形式的服务调用

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
@RestController
@RequestMapping("order")
public class OrderController {

// 使用 固定IP、Port
public static final String PAYMENT_URL_1 = "http://localhost:8004";

// 使用 注册中心的服务名
public static final String PAYMENT_URL_2 = "http://payment";

@Qualifier("restTemplate1")
@Autowired
private RestTemplate restTemplate1;

@Qualifier("restTemplate2")
@Autowired
private RestTemplate restTemplate2;

@GetMapping("/test1")
public String test1(@RequestParam String name) {
String msg = restTemplate1.getForObject(PAYMENT_URL_1 +"/pay/hello?name={1}", String.class, name);
String result = "[Order Service #test1]: " + msg;
return result;
}

@GetMapping("/test2")
public String test2(@RequestParam String name) {
String msg = restTemplate2.getForObject(PAYMENT_URL_2 +"/pay/hello?name={1}", String.class, name);
String result = "[Order Service #test2]: " + msg;
return result;
}

}

最后,在启动类上添加 @EnableDiscoveryClient 注解

1
2
3
4
5
6
7
8
9
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}

测试

启动payment、order服务,Consul的Web管理页面可以看出均注册成功

figure 2.jpeg

然后通过curl验证测试,服务调用正常符合预期,如下所示

figure 3.jpeg

参考文献

  1. Spring微服务实战 John Carnell著
请我喝杯咖啡捏~

欢迎关注我的微信公众号:青灯抽丝