Consul作为一款基于Go语言开发的开源工具,其可用于分布式系统的服务发现与配置
配置Consul
通过Docker先建立一个Consul服务
1 2 3 4 5 6 7
| docker pull consul:1.10
docker run -d -p 8500:8500 \ --name Consul-Service \ consul:1.10
|
然后,通过查看Consul的Web管理页面进行验证。 打开 http://localhost:8500 ,效果如下,符合预期
搭建服务提供者
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>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.2.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency>
<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> <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
---
spring: profiles: payment4 cloud: 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
---
spring: profiles: order3 cloud: 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 {
@Bean public RestTemplate restTemplate1() { return new RestTemplate(); }
@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 {
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管理页面可以看出均注册成功
然后通过curl验证测试,服务调用正常符合预期,如下所示
参考文献
- Spring微服务实战 John Carnell著