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. 新建Chrome标签页,极简+自用

    [跳转GitHub] chromeNewTab 已经入坑Chrome应用开发者,可以去:[应用商店地址]直接添加使用. 使用说明 下载chrome的一个[window组策略文件],解压文件后找到(\p ...

  2. 在FL Studio中有序地处理人声的混音轨道

    关于人声处理的技巧,我们在以前也有讲到很多,当然在以后也会有新的人声处理技巧课程,这是在音乐后期制作中无法避免的一个环节,在制作许多流行音乐时都会用到,今天先为大家讲解一下在FL Studio中更有序 ...

  3. Sonar检测Math.abs(new Random().nextInt()) “Use the original value instead”

    今天早上旁边同事喊我看一个Sonar检测出的问题: 当时看了好几眼没觉得这个有太大问题,于是又看了下Sonar建议: 这是说Math.abs()方法使用在数字上面可能返回最小值,觉得这个挺有意思的,于 ...

  4. leetcode 1046

    class Solution {       public int lastStoneWeight(int[] stones) {        MaxHeap s=new MaxHeap(stone ...

  5. 【HAOI2015】树上操作

    (题面来自洛谷) 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树 ...

  6. 你知道第一个C语言C++编译器是如何诞生的吗?

    当今几乎所有的实用的编译器/解释器(以下统称编译器)都是用 C 语言编写的,有一些语言比如 Clojure,Jython 等是基于 JVM 或者说是用 Java 实现的,IronPython 等是基于 ...

  7. CentOS7系统tab命令补全

    在新安装的CentOS7系统中,如果没有安装命令补全的话,在systemctl管理服务的时候就没法用tab来自动补全,因此在安装完系统后,我们要再安装命令补全这个软件: yum -y install ...

  8. Cassandra与职业发展 | 阿里云栾小凡 &#215; 蔚来汽车张旭东 &#215; 网龙阙乃祯

    # 活动精彩实录 | Cassandra与职业发展 点击此处观看完整活动录像​ 大家好,我叫邓为,我目前在DataStax担任领航架构师.我在DataStax工作了7年多的时间,也有7年多的Cassa ...

  9. Spring Boot 集成多个 Kafka

    一.配置文件 application.yml spring: kafka: one: bootstrap-servers: IP:PORT consumer: group-id: YOUR_GROUP ...

  10. MyBatis-01:环境搭建

    MyBatis-01:环境搭建 1.搭建实验数据库 CREATE DATABASE `mybatis`; USE `mybatis`; DROP TABLE IF EXISTS `user`; CRE ...