介绍 Spring Cloud Consul 组件,它是一个提供服务发现和配置的工具。consul具有分布式、高可用、高扩展性。
Consul 简介
Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其他分布式服务注册与发现的方案,Consul的方案更“一站式”,内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如ZooKeeper等)。使用起来也较 为简单。Consul使用Go语言编写,因此具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与Docker等轻量级容器可无缝配合 。
基于 Mozilla Public License 2.0 的协议进行开源. Consul 支持健康检查,并允许 HTTP 和 DNS 协议调用 API 存储键值对.
一致性协议采用 Raft 算法,用来保证服务的高可用. 使用 GOSSIP 协议管理成员和广播消息, 并且支持 ACL 访问控制.
Consul 的使用场景
docker 实例的注册与配置共享
coreos 实例的注册与配置共享
vitess 集群
SaaS 应用的配置共享
与 confd 服务集成,动态生成 nginx 和 haproxy 配置文件
Consul 的优势
使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是 Paxos, 而 etcd 使用的则是 Raft.
支持多数据中心,内外网的服务采用不同的端口进行监听。 多数据中心集群可以避免单数据中心的单点故障,而其部署则需要考虑网络延迟, 分片等情况等. zookeeper 和 etcd 均不提供多数据中心功能的支持.
支持健康检查. etcd 不提供此功能.
支持 http 和 dns 协议接口. zookeeper 的集成较为复杂, etcd 只支持 http 协议.
官方提供web管理界面, etcd 无此功能.
Consul 的角色
client: 客户端, 无状态, 将 HTTP 和 DNS 接口请求转发给局域网内的服务端集群.server: 服务端, 保存配置信息, 高可用集群, 在局域网内与本地客户端通讯, 通过广域网与其他数据中心通讯. 每个数据中心的 server 数量推荐为 3 个或是 5 个.
安装 Consul
Linux 64bit:
wget https://releases.hashicorp.com/consul/0.8.4/consul_0.8.4_linux_amd64.zip
unzip consul_0.8.4_linux_amd64.zip
sudo mv consul /bin
简单操作
启动:
consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node node1 -ui -bind 192.168.40.128 -client 192.168.40.128 -datacenter sz-1
或者:
consul agent -dev -client 192.168.40.128
查看成员:
consul members
查看节点:
curl 192.168.40.128:8500/v1/catalog/nodes
使用DNS协议查看节点信息:
dig @192.168.40.128 -p 8600 localhost.node.consul
注册服务
注册两个 Mysql 服务的实例, 数据中心在 sz-1, 端口都是 3306. 具体为以下命令:
[wsun@localhost ~]$ curl -X PUT -d '{"Datacenter": "sz-1", "Node": "mysql-1", "Address": "mysql-1.node.consul","Service": {"Service": "mysql", "tags": ["master","v1"], "Port": 3306}}' http://192.168.40.128:8500/v1/catalog/register
[wsun@localhost ~]$ curl -X PUT -d '{"Datacenter": "sz-1", "Node": "mysql-2", "Address": "mysql-2.node.consul","Service": {"Service": "mysql", "tags": ["slave","v1"],"Port": 3306}}'p://192.168.40.128:8500/v1/catalog/register
[wsun@localhost ~]$ curl http://192.168.40.128:8500/v1/catalog/service/mysql
[{"ID":"","Node":"mysql-1","Address":"mysql-1.node.consul","Datacenter":"sz-1","TaggedAddresses":null,"NodeMeta":null,"ServiceID":"mysql","ServiceName":"mysql","ServiceTags":["master","v1"],"ServiceAddress":"","ServicePort":3306,"ServiceEnableTagOverride":false,"CreateIndex":3662,"ModifyIndex":3662},{"ID":"","Node":"mysql-2","Address":"mysql-2.node.consul","Datacenter":"sz-1","TaggedAddresses":null,"NodeMeta":null,"ServiceID":"mysql","ServiceName":"mysql","ServiceTags":["slave","v1"],"ServiceAddress":"","ServicePort":3306,"ServiceEnableTagOverride":false,"CreateIndex":3665,"ModifyIndex":3665}]
dig @192.168.40.128 -p 8600 mysql.service.consul SRV
; <<>> DiG 9.9.4-RedHat-9.9.4-37.el7 <<>> @192.168.40.128 -p 8600 mysql.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 60960
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;mysql.service.consul. IN SRV
;; ANSWER SECTION:
mysql.service.consul. 0 IN SRV 1 1 3306 mysql-2.node.sz-1.consul.
mysql.service.consul. 0 IN SRV 1 1 3306 mysql-1.node.sz-1.consul.
;; ADDITIONAL SECTION:
mysql-2.node.sz-1.consul. 0 IN CNAME mysql-2.node.consul.
mysql-1.node.sz-1.consul. 0 IN CNAME mysql-1.node.consul.
;; Query time: 42 msec
;; SERVER: 192.168.40.128#8600(192.168.40.128)
;; WHEN: Mon Jun 26 02:00:07 PDT 2017
;; MSG SIZE rcvd: 288
构建工程
构建一个consul-miya的springboot工程,导入依赖pring-cloud-starter-consul-discovery,其依赖文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.forezp</groupId>
<artifactId>consul-hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>consul-hello</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
在其入口文件ConsulMiyaApplication加入注解@EnableDiscoveryClient,开启服务发现:
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class ConsulHelloApplication {
@RequestMapping("/hi")
public String home() {
return "Hello ,World";
}
public static void main(String[] args) {
new SpringApplicationBuilder(ConsulHelloApplication.class).web(true).run(args);
}
}
在其配置文件application.yml指定consul服务的端口为8500:
spring:
cloud:
consul:
host: localhost
port: 8500
discovery:
healthCheckPath: ${management.contextPath}/health
healthCheckInterval: 15s
instance-id: consul-hello
application:
name: consul-hello
server:
port: 8502
启动工程,访问localhost:8500,可以发现consul-hello被注册了。
源码下载:consul-hello