与Eureka相比,Consul不仅可用于服务发现,还可以用作基于微服务体系结构中的配置服务器。我们可以通过以下方式引入Consul所需的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-all</artifactId>
</dependency>
当我们引入该依赖的时候,等同于将以下几个依赖添加进了应用
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-bus</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<scope>compile</scope>
<optional>true</optional>
</dependency>
本次我们只关注Consul的服务发现功能,所以只需要添加以下依赖即可:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
一:向Consul进行服务注册(Registering with Consul)
当客户端(client )向Consul注册时,它会提供有关自身的元数据,如主机(host)和端口(port)、id、名称(name)和标记(tags)。默认情况下,会创建一个HTTP检查,Consul每10秒访问一次/health端点。如果运行状况检查失败,则将服务实例标记为严重。
默认情况下,Spring尝试在地址localhost:8500上与Consul连接。如果您需要覆盖此地址,则安装下面的格式进行配置即可,例如(在application.yml中):
spring:
cloud:
inetutils:
preferred-networks: #springcloud提供工具,解决多IP地址问题
- 10.2.2.9
- 172.18.88.209
consul:
host: localhost
port: 8500
如果使用Spring Cloud Consul Config,则需要将上述值放在bootstrap.yml而不是application.yml中。
默认的服务名(service name)、实例Id(instance id)、端口(port)取自Spring环境参数对象Environment中的${spring.application.name}、Spring Context ID和${server.port} 的值
如果要禁用Consul Discovery Client,您可以设置spring.cloud.consul.discovery.enabled为false,或者设置spring.cloud.discovery.enabled为false均可。
如果要禁止服务的注册,可设置spring.cloud.consul.discovery.register为false.
当管理服务器端口(management server port)设置为与应用程序端口不同的端口时,通过设置management.server.port属性,管理服务(management service )将注册为与应用程序服务不同的单独服务。例如(application.yml):
spring:
application:
name: myApp
management:
server:
port: 4452
此时会注册两个服务
Application Service | Management Service |
---|---|
instanceId : myApp Name: myApp |
instanceId : myApp-management Name: myApp-management |
这里在进行服务注册的时候默认是使用了应用的名称,可以通过以下的方式来修改注册的名称从而与应用名称不同
spring:
application:
name: myApp
management:
server:
port: 4452
spring:
cloud:
consul:
discovery:
instance-id: ${spring.application.name}-${server.port}-${spring.cloud.client.ip-address} #Consuls使用的唯一标识。如果多个服务一样则Consul只会保留一个,默认:${spring.application.name}-${server.port}; 也可用:${spring.application.name}-${server.port}-${spring.cloud.client.hostname}
serviceName: ${spring.application.name}
tags: version=1.0
prefer-ip-address: true #开启使用IP而非主机名注册,根据需要选择是否开启
#ip-address: 10.2.2.9 #直接指定IP地址(也可使用上面的inetutils方案)
此时注册的两个服务的ID和名称分别如下:
Application Service | Management Service |
---|---|
instanceId : custom-service-id Name: myprefix-myApp |
instanceId : custom-service-id-management Name: myprefix-myApp-management |
从结果可见,Management服务的ID和名称都会在Application服务的基础上加上后缀“-management”,这是默认值,我们可以通过下面的参数来进行修改
/** Port to register the management service under (defaults to management port) */
spring.cloud.consul.discovery.management-port
/** Suffix to use when registering management service (defaults to "management" */
spring.cloud.consul.discovery.management-suffix
/** Tags to use when registering management service (defaults to "management" */
spring.cloud.consul.discovery.management-tags
健康检查
Consul 实例的健康检查默认为“/health”,这是Spring Boot Actuator 应用程序中有用端点的默认位置。如果使用非默认的上下文路径(context path)或servlet路径(例如server.servletPath=/foo)或管理端点路径(例如management.server.servlet.context-path=/admin),则即使是Actuator 应用程序,也需要更改这些内容。Consul用来检查健康端点(health endpoint)的时间间隔也可以配置。例如:10秒(10s)或1分钟(1m)。例子:
spring:
cloud:
consul:
discovery:
healthCheckPath: ${management.server.servlet.context-path}/health
healthCheckInterval: 15s
当然,你也可以通过设置management.health.consul.enabled=false来禁用健康检查。
二:服务发现
Spring Cloud中可以使用Feign或RestTemplate利用Ribbon来进行客户端负载均衡,其与Ribbon的集成在启动时自动完成。
由于Spring Cloud Ribbon正在维护中,建议您将spring.cloud.loadbalancer.ribbon.enabled设置为false,以便使用BlockingLoadBalancerClient 而不是RibbonLoadBalancerClient。
假设使用RestTemplate来访问“STORES”服务,则可以使用类似下面的代码:
@Autowired
RestTemplate restTemplate;
public String getFirstProduct() {
return this.restTemplate.getForObject("https://STORES/products/1", String.class);
}
但是,如果“STORES”服务并不在当前的数据中心中,则还需要添加以下的配置告知该服务所在的数据中心才行
spring.cloud.consul.discovery.datacenters.STORES=dc-west
这里的dc-west就是STORES所在的数据中心。
使用DiscoveryClient
您还可以使用org.springframework.cloud.client.discovery.DiscoveryClient提供的简单API来进行服务的发现操作,如下所示:
@Autowired
private DiscoveryClient discoveryClient;
public String serviceUrl() {
List<ServiceInstance> list = discoveryClient.getInstances("STORES");
if (list != null && list.size() > 0 ) {
return list.get(0).getUri();
}
return null;
}
以上便是使用Consul进行服务发现的使用方法,至于更深入的分析将留在后面的章节。