1. Consul简介

  Consul是HashiCorp公司推出的开源软件,它提供了一套分布式高可用可横向扩展的解决方案,能为微服务提供服务治理、健康检查、配置共享等能力。

  Eurake2.x停止更新后,Spirng Cloud官网也推荐使用Consul实现服务注册与发现。并且可以代替Sping Cloud Config实现配置中心。

  官网:https://www.consul.io/

2. 功能特点

  • 服务发现

      提供服务注册和服务发现的功能,通过DNS和Http获取服务信息。
  • 健康检查

      通过健康检查可以避免请求被路由到不健康的服务,并且主动断开使其不再具备服务能力。
  • 键值存储

      提供动态配置功能,通过长轮询实现配置变更的即时通知。
  • 多数据中心

      通过简单配置即可实现多数据中心,并且可以获得其他数据中心的服务。
  • UI界面

      通过界面即可获取服务信息、配置信息等其他信息。

3. CAP原则

  CAP原则指的是在分布式系统中Consistency(一致性)、Availability(可用性)、Partition Tolerance(分区容错性)总是不能同时成立。

  一致性:它要求在任一时刻点分布式系统中的所有数据都处于同一状态。

  可用性:在系统集群的一部分节点宕机后,系统依然能够响应用户的请求。

  分区容错性:在网络区间通信出现异常系统能容错处理。

  一般来说,网络总是存在不稳定性,分区容错也总是存在的,所以默认CAP中的P总是成立的。

  一致性要求在任一时刻数据状态一致,必然需要加锁,因此不能保证可用性,反之同理。因此一致性和可用性总是互斥的。

4. 常见服务发现与注册方案对比

功能 Eureka Consul Zookeeper Nacos
CAP AP CP CP CP+AP
一致性算法 Raft Paxos Raft
访问协议 Http Http/DNS TCP Http/DNS
健康检查 可配支持 支持 支持 支持
多数据中心 x 支持 x 支持
键值存储 支持 支持 支持 支持
雪崩保护 支持 x x 支持
自动注销实例 支持 x 支持 支持
监听支持 支持 支持 支持 支持
安全性 x ACL/Https ACL ACL/Https
SpringCloud集成 支持 支持 支持 支持
Dubbo集成 x x 支持 支持
K8S集成 x 支持 x 支持

  Consul采用Raft算法来保证数据的强一致性,虽然优势明显,但是也牺牲了一些特性:

  (1) 服务注册比Eureka慢。因为Consul要求必须节点数过半才认为注册成功;

  (2) Leader挂掉后,在重新选举期间,Consul将不可用,为了一致性牺牲可用性。

5. Consul架构



  图中有两个数据中心:DATACENTER1、DATACENTER2,每个数据中心都有3个Server节点,该数量使得在故障转移和性能之间达到平衡。

6. Consul端口说明

端口 说明
TCP/8300 用于服务器节点。客户端通过该端口 RPC 协议调用服务端节点。
TCP/UDP/8301 用于单个数据中心所有节点之间的互相通信,即对 LAN 池信息的同步。它使得整个数据中心能够自动发现服务器地址,分布式检测节点故障,事件广播(如Leader选举事件)。
TCP/UDP/8302 用于单个或多个数据中心之间的服务器节点的信息同步,即对 WAN 池信息的同步。它针对互联网的网络高延迟进行了优化,能够实现跨数据中心请求。
8500 基于 HTTP 协议,用于 API 接口或 WEB UI 访问。
8600 作为 DNS 服务器,通过节点名查询节点信息。

7. Spring Cloud Consul实现服务注册发现

创建生产者1:

  • 创建Maven项目

  • 修改pom.xml
<?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>
<artifactId>spring-cloud-consul-producer1</artifactId>
<name>spring-cloud-consul-producer1</name> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR5</spring-cloud.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<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>${spring-cloud.version}</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>
  • 创建Controller
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; /**
* 业务Controller
*
* @author CL
*
*/
@RestController
public class BookController { /**
* 业务接口
*
* @return
*/
@RequestMapping(value = "/get")
public String get() {
return "Consul-1";
} }
  • 创建启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /**
* 启动类
*
* @author CL
*
*/
@SpringBootApplication
@EnableDiscoveryClient
public class ConsulProducerApplication { public static void main(String[] args) {
SpringApplication.run(ConsulProducerApplication.class, args);
} }
  • 创建application.yml
server:
port: 9001 spring:
application:
name: spring-cloud-consul-producer
cloud:
consul:
discovery:
serviceName: consul-producer
host: 127.0.0.1
port: 8500

创建生产者2:

  • 创建Maven项目

  • 修改pom.xml
<?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>
<artifactId>spring-cloud-consul-producer2</artifactId>
<name>spring-cloud-consul-producer2</name> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR5</spring-cloud.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<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>${spring-cloud.version}</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>
  • 创建Controller
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; /**
* 业务Controller
*
* @author CL
*
*/
@RestController
public class BookController { /**
* 业务接口
*
* @return
*/
@RequestMapping(value = "/get")
public String get() {
return "Consul-2";
} }
  • 创建启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /**
* 启动类
*
* @author CL
*
*/
@SpringBootApplication
@EnableDiscoveryClient
public class ConsulProducerApplication { public static void main(String[] args) {
SpringApplication.run(ConsulProducerApplication.class, args);
} }
  • 创建application.yml
server:
port: 9002 spring:
application:
name: spring-cloud-consul-producer
cloud:
consul:
discovery:
serviceName: consul-producer
host: 127.0.0.1
port: 8500

创建消费者:

  • 创建Maven项目

  • 修改pom.xml
<?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>
<artifactId>spring-cloud-consul-consumer</artifactId>
<name>spring-cloud-consul-consumer</name> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR5</spring-cloud.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<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>${spring-cloud.version}</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>
  • 创建Controller
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; /**
* 服务Controller
*
* @author CL
*
*/
@RestController
public class ServicesController { @Autowired
private DiscoveryClient discoveryClient; @Autowired
private LoadBalancerClient loadBalancerClient; /**
* 获得所以服务列表
*
* @return
*/
@RequestMapping(value = "/getAllServices")
public List<ServiceInstance> getAllServices() {
return discoveryClient.getInstances("consul-producer");
} /**
* 获取服务Uri
*
* @return
*/
@RequestMapping("/getServiceUri")
public String getServiceUri() {
return loadBalancerClient.choose("consul-producer").getUri().toString();
} /**
* 负载均衡调用提供者接口
*
* @return
*/
@RequestMapping("/loadBalancer")
public String call() {
ServiceInstance serviceInstance = loadBalancerClient.choose("consul-producer");
return new RestTemplate().getForObject(serviceInstance.getUri().toString() + "/get", String.class);
}
}
  • 创建启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; /**
* 启动类
*
* @author CL
*
*/
@SpringBootApplication
public class ConsulConsumerApplication { public static void main(String[] args) {
SpringApplication.run(ConsulConsumerApplication.class, args);
} }
  • 创建application.yml
server:
port: 9003 spring:
application:
name: spring-cloud-consul-consumer
cloud:
consul:
discovery:
register: false
host: 127.0.0.1
port: 8500

部署Consul:

  Consul安装部署(Windows单机、Docker集群)

启动项目:

  启动顺序:生产者1 -> 生产者2 -> 消费者

  访问Consul WEB UI:http://127.0.0.1:8500





测试:

  • 获取全部服务信息
curl http://localhost:9003/getAllServices

#返回:

[
{
"instanceId": "spring-cloud-consul-producer-9001",
"serviceId": "consul-producer",
"host": "192.168.0.100",
"port": 9001,
"secure": false,
"metadata": {
"secure": "false"
},
"uri": "http://192.168.0.100:9001",
"scheme": null
},
{
"instanceId": "spring-cloud-consul-producer-9002",
"serviceId": "consul-producer",
"host": "192.168.0.100",
"port": 9002,
"secure": false,
"metadata": {
"secure": "false"
},
"uri": "http://192.168.0.100:9002",
"scheme": null
}
]
  • 获取服务Uri(负载均衡)
#第一次调用:
curl http://localhost:9003/getServiceUri #返回: http://192.168.0.100:9001 #第二次调用:
curl http://localhost:9003/getServiceUri #返回: http://192.168.0.100:9002
  • 调用提供者接口(负载均衡)
#第一次调用:
curl http://localhost:9003/loadBalancer #返回: Consul-1 #第二次调用:
curl http://localhost:9003/loadBalancer #返回: Consul-2

8. Spring Cloud Consul实配置中心

  • 创建Maven项目

  • 修改pom.xml
<?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>
<artifactId>spring-cloud-consul-config</artifactId>
<name>spring-cloud-consul-config</name> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR5</spring-cloud.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</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>${spring-cloud.version}</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>
  • 创建application.yml
server:
port: 9004
  • 创建bootstrap.yml

      作为配置中心的相关配置必须写到bootstrap.yml
spring:
application:
name: spring-cloud-consul-config
cloud:
consul:
discovery:
service-name: consul-config
host: 127.0.0.1
port: 8500
config:
# 是否启用配置中心功能
enabled: true
# 设置配置所在目录
prefix: config
# 设置应用程序使用的文件夹名称,默认application
defaultContext: application
# 配置key的名字,由于Consul是K/V存储,配置存储在对应K的V中,配置文件路径为:/config/application/key
data-key: data
# 设置配置值的格式,四种配置:YAML PROPERTIES KEY-VALUE FILES
format: YAML
# 设置配置的分隔符
profile-separator: ','
  • 创建Controller
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; /**
* 配置Controller
*
* @author CL
*
*/
@RestController
@RefreshScope
public class ConfigController { @Value("${project-name}")
private String projectName; @RequestMapping(value = "/getInfo")
public String getInfo() {
return projectName;
} }
  • 创建启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; /**
* 启动类
*
* @author CL
*
*/
@SpringBootApplication
@EnableDiscoveryClient
public class ConsulConfigApplication { public static void main(String[] args) {
SpringApplication.run(ConsulConfigApplication.class, args);
} }
  • 创建配置

      在Consul WEB UI的Key/Value下创建配置:

  • 启动项目
  • 查看Consul WEB UI

  • 测试
curl http://localhost:9004/getInfo

#返回:

spring-cloud-consul-demo

9. 项目地址

  spring-cloud-consul-demo

Consul 多数据中心下的服务注册发现与配置共享的更多相关文章

  1. 服务注册发现、配置中心集一体的 Spring Cloud Consul

    前面讲了 Eureka 和 Spring Cloud Config,今天介绍一个全能选手 「Consul」.它是 HashiCorp 公司推出,用于提供服务发现和服务配置的工具.用 go 语言开发,具 ...

  2. spring-cloud-consul 服务注册发现与配置

    下面是 Spring Cloud 支持的服务发现软件以及特性对比(Eureka 已停止更新,取而代之的是 Consul): Feature euerka Consul zookeeper etcd 服 ...

  3. 服务注册发现与注册中心对比-Eureka,Consul,Zookeeper,Nacos对比

    服务注册发现与注册中心对比-Eureka,Consul,Zookeeper,Nacos对比 注册中心简介 流程和原理 基础流程 核心功能 1.Eureka.Consul.Zookeeper三者异同点 ...

  4. 基于docker,consul,consul-template, registrator, nginx服务注册发现集群

      介绍 该工程主要实现服务的自动注册发现,从而达到提高运维效率,做到服务的自动发现和动态扩展. 服务注册发现 服务启动后自动被发现 动态变更负载均衡 自动伸缩 工具 1.Registrator 这是 ...

  5. 服务注册发现consul之二:在Spring Cloud中使用Consul实现服务的注册和发现

    首先安装consul环境,参照之前的文章:<服务注册发现consul之一:consul介绍及安装>中的第一节介绍. Spring Cloud使用Consul的服务与发现 1.导入依赖pri ...

  6. CoSky 高性能 服务注册/发现 & 配置中心

    CoSky 基于 Redis 的服务治理平台(服务注册/发现 & 配置中心) Consul + Sky = CoSky CoSky 是一个轻量级.低成本的服务注册.服务发现. 配置服务 SDK ...

  7. 服务注册发现Eureka之二:高可用服务注册中心

    前言 在Spring Cloud系列文章的开始,我们就介绍了服务注册与发现,其中,主要演示了如何构建和启动服务注册中心Eureka Server,以及如何将服务注册到Eureka Server中,但是 ...

  8. python与consul 实现gRPC服务注册-发现

    背景 通过对gRPC的介绍我们知道,当正常启动服务后,我们只需要知道ip,port就可以进行gRPC的连接.可以想到,这种方式并不适合用于线上环境,因为这样直连的话就失去了扩展性,当需要多机部署的时候 ...

  9. consul服务发现和配置共享的软件,

    Consul 是什么 consul是一个支持多数据中心分布式高可用服务发现和配置共享的服务软件,由HashiCorp 公司用 Go 语言开发, 基于 Mozilla Public License 2. ...

随机推荐

  1. No matching distribution found for Tensorflow

    No matching distribution found for Tensorflow 原因:python 3.7.3 版本过高 解决:安装3.6  64位

  2. 还不懂spring中的bean的话,你一定得好好看看这篇文章

    bean的作用域 bean的生命周期 bean的装配 代码 实体类 package com; import java.util.List; public class User { private St ...

  3. Guitar Pro小课堂——如何进行消音

    在我们弹吉他时,消音技术是必须掌握的一项吉他技能.在我们遇到休止符时.乐曲结束时.乐段,乐句中止时.吉他旋律的分句,呼吸处:变换和弦时的低音(尤其是空弦低音).断奏.弹奏强音时其他空弦被激起的共鸣音( ...

  4. CorelDRAW X7 X8 2017 2018是什么关系?

    从CorelDRAW 2017版本开始我们叫习惯了的X几系列的CorelDRAW毅然决然的就换了称呼,所以有时候很多朋友对于软件版本,经常会傻傻分不清,还有人认为X8版本比2017版本高,究竟为什么会 ...

  5. 「LOJ 3153」 「JOI Open 2019」三级跳

    题面 LOJ 3153 solution 对于任意一对\(A,B\),若区间\([A,B]\)中存在一个数权值大于\(A\)或\(B\),则用这个数来替代\(A\)或\(B\)显然更优. 故只需要考虑 ...

  6. MarkDown学习总结-2020.05.11

    1.使用工具 1.1Typora 官网地址:https://www.typora.io/ 下载链接 2.基础入门 注意: []中的内容则是对应格式的标记符,默认全部标识符后面需要多加一个空格才能生效. ...

  7. zabbix 监控文件夹

    安装inotify wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz tar -zx ...

  8. [COCI2016-2017#1] Mag 结论证明

    结论:最多包含一个 \(2\),并且不在链的两端点. 证明:我们问题分成两个 \(\texttt{pass}\). \(\texttt{pass 1}\):\(\forall u,s.t.x_{u}\ ...

  9. 2018-div-matrix 题解(打表)

    题目链接 题目大意 要你求有多少个满足题目条件的矩阵mod 1e9+7 \(a[1][1]=2018\;\;a[i][j]为a[i-1][j]和a[i][j-1]的因子\) 题目思路 dp也就图一乐, ...

  10. Java基础教程——数组

    数组 Java数组:用于存储同一种数据类型的多个数据. Java数组本身是一种数据类型--引用类型. 类(String.Scanner等大写字母开头的类型)也属于引用类型,int.double等基本类 ...