Spring Cloud Consul 实现服务注册与发现
1、前言
本文通过创建 provider-service、consumer-service 两个微服务,并通过 feign 接口调用来演示 Spring Cloud 整合 Consul。阅读本文需要前置知识:
- Spring Boot
- Spring Cloud
- Spring Cloud Feign
2、搭建 provider-service 服务
2.1、创建 maven 模块
创建provider项目,添加provider-service、provider-service-remote-api两个maven模块:
2.2、添加 spring boot、spring cloud 依赖
在父模块provider中添加spring boot、spring cloud依赖,spring cloud使用截止当前最新版本Hoxton.SR1,关联spring boot版本2.2.2.RELEASE
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<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>
注意:spring boot和spring cloud之间有版本依赖关系,如果想用其他版本,请自行查询对应的依赖版本,否则可能由于不兼容服务起不来
2.3、provider-service-remote-api模块编写feign接口
maven模块provider-service-remote-api引入spring cloud feign
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
代码编写,新建IProviderRemoteService接口
@FeignClient(name = "provider-service")
public interface IProviderRemoteService {
@RequestMapping(value = "hello", method = RequestMethod.GET)
String hello();
}
2.4、provider-service模块编写接口实现
maven 依赖
<dependency>
<groupId>com.example</groupId>
<artifactId>provider-service-remote-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
接口实现类ProviderRemoteService
@RestController
public class ProviderRemoteService implements IProviderRemoteService {
@Override
public String hello() {
return "hello world!";
}
}
2.5、集成spring cloud consul
引入spring cloud consul模块
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
application.yml添加consul配置
server:
port: 8080
spring:
application:
name: provider-service
cloud:
consul:
host: 127.0.0.1
port: 8500
discovery:
heartbeat:
enabled: true
启动类添加@EnableDiscoveryClient
注解,启用服务发现功能
@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
到此,provider-service服务已经全部搭建完毕,完整项目结构:
3、搭建 consumer-service 服务
3.1、创建 maven 模块
创建consumer项目,添加consumer-service,因为该服务不需要对外提供接口,所以无需consumer-service-remote-api模块:
3.2、consumer-service 编写接口调用 provider-service服务
引用provider-service-remote-api
<dependency>
<groupId>com.example</groupId>
<artifactId>provider-service-remote-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
编写测试接口,通过feign调用provider-service服务
@RestController
public class ConsumerController {
@Autowired
private IProviderRemoteService providerRemoteService;
@RequestMapping(value = "/test")
public String test() {
return providerRemoteService.hello();
}
}
3.3、集成 spring cloud consul
同provider-service服务一样,引入spring cloud consul模块
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
application.yml添加consul配置
server:
port: 9090
spring:
application:
name: consumer-service
cloud:
consul:
host: 127.0.0.1
port: 8500
discovery:
heartbeat:
enabled: true
启动类添加@EnableDiscoveryClient
注解,启用服务发现功能,并添加@EnableFeignClients
注解,启用feign功能
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
到此,consumer-service服务也搭建完成,完整项目结构:
4、测试
4.1、启动 consul 服务
为了便于测试,笔者在本机以开发者模式起了一个consul服务
D:\consul>consul agent -dev
==> Starting Consul agent...
Version: 'v1.7.0'
Node ID: 'c43eedeb-f211-dbf2-e3fa-3caa64f86ddb'
Node name: 'DESKTOP-77V3R9P'
Datacenter: 'dc1' (Segment: '<all>')
Server: true (Bootstrap: false)
Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false
==> Log data will now stream in as it occurs:
2020-02-22T15:34:07.878+0800 [DEBUG] agent: Using random ID as node ID: id=c43eedeb-f211-dbf2-e3fa-3caa64f86ddb
2020-02-22T15:34:07.900+0800 [DEBUG] agent.tlsutil: Update: version=1
2020-02-22T15:34:07.914+0800 [DEBUG] agent.tlsutil: OutgoingRPCWrapper: version=1
2020-02-22T15:34:07.916+0800 [INFO] agent.server.raft: initial configuration: index=1 servers="[{Suffrage:Voter ID:c43eedeb-f211-dbf2-e3fa-3caa64f86ddb Address:127.0.0.1:8300}]"
2020-02-22T15:34:07.916+0800 [INFO] agent.server.raft: entering follower state: follower="Node at 127.0.0.1:8300 [Follower]" leader=
2020-02-22T15:34:07.919+0800 [INFO] agent.server.serf.wan: serf: EventMemberJoin: DESKTOP-77V3R9P.dc1 127.0.0.1
2020-02-22T15:34:07.920+0800 [INFO] agent.server.serf.lan: serf: EventMemberJoin: DESKTOP-77V3R9P 127.0.0.1
2020-02-22T15:34:07.920+0800 [INFO] agent.server: Adding LAN server: server="DESKTOP-77V3R9P (Addr: tcp/127.0.0.1:8300) (DC: dc1)"
2020-02-22T15:34:07.921+0800 [INFO] agent.server: Handled event for server in area: event=member-join server=DESKTOP-77V3R9P.dc1 area=wan
2020-02-22T15:34:07.921+0800 [INFO] agent: Started DNS server: address=127.0.0.1:8600 network=udp
2020-02-22T15:34:07.923+0800 [INFO] agent: Started DNS server: address=127.0.0.1:8600 network=tcp
2020-02-22T15:34:07.926+0800 [INFO] agent: Started HTTP server: address=127.0.0.1:8500 network=tcp
2020-02-22T15:34:07.928+0800 [INFO] agent: started state syncer
==> Consul agent running!
...
4.2、启动服务注册到 consul
分别启动provider-service服务和consumer-service服务,访问consul的Web UI界面可以看到两个服务都注册上来了:
4.3、调用测试接口
调用consumer-service测试接口 http://127.0.0.1:9090/test
现在尝试把provider服务停止,consul注册中心可以看到健康检查状态为Critical
,服务已经下线
此时,再次调用 consumer-service 测试接口,会报找不到服务
5、Spring Cloud Consul 应用配置
Name | Default | Description |
---|---|---|
spring.cloud.consul.config.acl-token | ||
spring.cloud.consul.config.data-key | data | If format is Format.PROPERTIES or Format.YAML then the following field is used as key to look up consul for configuration. |
spring.cloud.consul.config.default-context | application | |
spring.cloud.consul.config.enabled | TRUE | |
spring.cloud.consul.config.fail-fast | TRUE | Throw exceptions during config lookup if true, otherwise, log warnings. |
spring.cloud.consul.config.format | ||
spring.cloud.consul.config.name | Alternative to spring.application.name to use in looking up values in consul KV. | |
spring.cloud.consul.config.prefix | config | |
spring.cloud.consul.config.profile-separator | , | |
spring.cloud.consul.config.watch.delay | 1000 | The value of the fixed delay for the watch in millis. Defaults to 1000. |
spring.cloud.consul.config.watch.enabled | TRUE | If the watch is enabled. Defaults to true. |
spring.cloud.consul.config.watch.wait-time | 55 | The number of seconds to wait (or block) for watch query, defaults to 55. Needs to be less than default ConsulClient (defaults to 60). To increase ConsulClient timeout create a ConsulClient bean with a custom ConsulRawClient with a custom HttpClient. |
spring.cloud.consul.discovery.acl-token | ||
spring.cloud.consul.discovery.catalog-services-watch-delay | 1000 | The delay between calls to watch consul catalog in millis, default is 1000. |
spring.cloud.consul.discovery.catalog-services-watch-timeout | 2 | The number of seconds to block while watching consul catalog, default is 2. |
spring.cloud.consul.discovery.consistency-mode | Consistency mode for health service request. | |
spring.cloud.consul.discovery.datacenters | Map of serviceId’s → datacenter to query for in server list. This allows looking up services in another datacenters. | |
spring.cloud.consul.discovery.default-query-tag | Tag to query for in service list if one is not listed in serverListQueryTags. | |
spring.cloud.consul.discovery.default-zone-metadata-name | zone | Service instance zone comes from metadata. This allows changing the metadata tag name. |
spring.cloud.consul.discovery.deregister | TRUE | Disable automatic de-registration of service in consul. |
spring.cloud.consul.discovery.enabled | TRUE | Is service discovery enabled? |
spring.cloud.consul.discovery.fail-fast | TRUE | Throw exceptions during service registration if true, otherwise, log warnings (defaults to true). |
spring.cloud.consul.discovery.health-check-critical-timeout | Timeout to deregister services critical for longer than timeout (e.g. 30m). Requires consul version 7.x or higher. | |
spring.cloud.consul.discovery.health-check-headers | Headers to be applied to the Health Check calls. | |
spring.cloud.consul.discovery.health-check-interval | 10s | How often to perform the health check (e.g. 10s), defaults to 10s. |
spring.cloud.consul.discovery.health-check-path | /actuator/health | Alternate server path to invoke for health checking. |
spring.cloud.consul.discovery.health-check-timeout | Timeout for health check (e.g. 10s). | |
spring.cloud.consul.discovery.health-check-tls-skip-verify | Skips certificate verification during service checks if true, otherwise runs certificate verification. | |
spring.cloud.consul.discovery.health-check-url | Custom health check url to override default. | |
spring.cloud.consul.discovery.heartbeat.enabled | FALSE | |
spring.cloud.consul.discovery.heartbeat.interval-ratio | ||
spring.cloud.consul.discovery.heartbeat.ttl | 30s | |
spring.cloud.consul.discovery.hostname | Hostname to use when accessing server. | |
spring.cloud.consul.discovery.include-hostname-in-instance-id | FALSE | Whether hostname is included into the default instance id when registering service. |
spring.cloud.consul.discovery.instance-group | Service instance group. | |
spring.cloud.consul.discovery.instance-id | Unique service instance id. | |
spring.cloud.consul.discovery.instance-zone | Service instance zone. | |
spring.cloud.consul.discovery.ip-address | IP address to use when accessing service (must also set preferIpAddress to use). | |
spring.cloud.consul.discovery.lifecycle.enabled | TRUE | |
spring.cloud.consul.discovery.management-port | Port to register the management service under (defaults to management port). | |
spring.cloud.consul.discovery.management-suffix | management | Suffix to use when registering management service. |
spring.cloud.consul.discovery.management-tags | Tags to use when registering management service. | |
spring.cloud.consul.discovery.order | 0 | Order of the discovery client used by?CompositeDiscoveryClient?for sorting available clients. |
spring.cloud.consul.discovery.port | Port to register the service under (defaults to listening port). | |
spring.cloud.consul.discovery.prefer-agent-address | FALSE | Source of how we will determine the address to use. |
spring.cloud.consul.discovery.prefer-ip-address | FALSE | Use ip address rather than hostname during registration. |
spring.cloud.consul.discovery.query-passing | FALSE | Add the 'passing` parameter to /v1/health/service/serviceName. This pushes health check passing to the server. |
spring.cloud.consul.discovery.register | TRUE | Register as a service in consul. |
spring.cloud.consul.discovery.register-health-check | TRUE | Register health check in consul. Useful during development of a service. |
spring.cloud.consul.discovery.scheme | http | Whether to register an http or https service. |
spring.cloud.consul.discovery.server-list-query-tags | Map of serviceId’s → tag to query for in server list. This allows filtering services by a single tag. | |
spring.cloud.consul.discovery.service-name | Service name. | |
spring.cloud.consul.discovery.tags | Tags to use when registering service. | |
spring.cloud.consul.enabled | TRUE | Is spring cloud consul enabled. |
spring.cloud.consul.host | localhost | Consul agent hostname. Defaults to ‘localhost’. |
spring.cloud.consul.port | 8500 | Consul agent port. Defaults to ‘8500’. |
spring.cloud.consul.retry.initial-interval | 1000 | Initial retry interval in milliseconds. |
spring.cloud.consul.retry.max-attempts | 6 | Maximum number of attempts. |
spring.cloud.consul.retry.max-interval | 2000 | Maximum interval for backoff. |
spring.cloud.consul.retry.multiplier | 1.1 | Multiplier for next interval. |
spring.cloud.consul.scheme | Consul agent scheme (HTTP/HTTPS). If there is no scheme in address - client will use HTTP. | |
spring.cloud.consul.tls.certificate-password | Password to open the certificate. | |
spring.cloud.consul.tls.certificate-path | File path to the certificate. | |
spring.cloud.consul.tls.key-store-instance-type | Type of key framework to use. | |
spring.cloud.consul.tls.key-store-password | Password to an external keystore. | |
spring.cloud.consul.tls.key-store-path | Path to an external keystore. |