Consul 介绍
Consul 是 HashiCorp 公司推出的开源工具, 用于实现分布式系统的服务发现与配置. 与其它分布式服务注册与发现的方案, Consul 的方案更 "一站式", 内置了服务注册与发现框 架, 分布一致性协议实现, 健康检查, Key/Value 存储, 多数据中心方案, 不再需要依赖其它工具 (比如 ZooKeeper 等). 使用起来也较 为简单. Consul 使用 Go 语言编写, 因此具有天然可移植性 (支持 Linux,Windows 和 Mac OS X); 安装包仅包含一个可执行文件, 方便部署, 与 Docker 等轻量级容器可无缝配合.
Consul 的优势:
使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是 Paxos, 而 etcd 使用的则是 Raft.
支持多数据中心, 内外网的服务采用不同的端口进行监听. 多数据中心集群可以避免单数据中心的单点故障, 而其部署则需要考虑网络延迟, 分片等情况等. zookeeper 和 etcd 均不提供多数据中心功能的支持.
支持健康检查. etcd 不提供此功能.
支持 http 和 dns 协议接口. zookeeper 的集成较为复杂, etcd 只支持 http 协议.
官方提供 web 管理界面, etcd 无此功能.
综合比较, Consul 作为服务注册和配置管理的新星, 比较值得关注和研究.
特性:
服务发现
健康检查
Key/Value 存储
多数据中心
Consul 角色
client: 客户端, 无状态, 将 HTTP 和 DNS 接口请求转发给局域网内的服务端集群.
server: 服务端, 保存配置信息, 高可用集群, 在局域网内与本地客户端通讯, 通过广域网与其它数据中心通讯. 每个数据中心的 server 数量推荐为 3 个或是 5 个.
Consul 客户端, 服务端还支持夸中心的使用, 更加提高了它的高可用性.
Consul 工作原理:
1, 当 Producer 启动的时候, 会向 Consul 发送一个 post 请求, 告诉 Consul 自己的 IP 和 Port
2,Consul 接收到 Producer 的注册后, 每隔 10s(默认) 会向 Producer 发送一个健康检查的请求, 检验 Producer 是否健康
3, 当 Consumer 发送 GET 方式请求 /API/address 到 Producer 时, 会先从 Consul 中拿到一个存储服务 IP 和 Port 的临时表, 从表中拿到 Producer 的 IP 和 Port 后再发送 GET 方式请求 /API/address
4, 该临时表每隔 10s 会更新, 只包含有通过了健康检查的 Producer
Consul 的安装
从官网 https://www.consul.io/downloads.html 下载对应的版本, 这里下载的是 Windows 版本, 然后 cmd 命令启动, 在浏览器输入 http://localhost:8500/ , 有正常页面输出则启动成功
consul agent -dev # -dev 表示开发模式运行, 另外还有 - server 表示服务模式运行
Consul 服务端
1. 引入依赖
这里需要引入 spring-cloud-starter-consul-discovery,spring-cloud-starter-consul-all,consul-API,spring-boot-starter-actuator, 参考博客未引入 spring-cloud-starter-consul-all,consul-API 两个依赖, 在我测试的时候报阿里云仓库找不到 502 的错误.
- <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.1.8.RELEASE</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
- <groupId>com.example</groupId>
- <artifactId>SpringCloudConsulProducer</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>SpringCloudConsulProducer</name>
- <description>Demo project for Spring Boot</description>
- <properties>
- <java.version>1.8</java.version>
- <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-Web</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-all</artifactId>
- <version>2.1.3.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>com.ecwid.consul</groupId>
- <artifactId>consul-API</artifactId>
- <version>1.4.2</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-tomcat</artifactId>
- <scope>provided</scope>
- </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>
- <packaging>war</packaging>
- </project>
- View Code
2. 配置文件
- server.port=8764
- spring.application.name=consul-provider
- spring.cloud.consul.host=127.0.0.1
- spring.cloud.consul.port=8500
- spring.cloud.consul.discovery.service-name=consul-provider
3. 在 main 类中添加 @EnableDiscoveryClient 注解
4. 增加 Controller
这里创建了 HelloController, 这里需要添加 @RestController 注解, 如果没添加在客户端调用的时候就会报 404 的错误.
- package com.example.demo;
- import org.springframework.Web.bind.annotation.RequestMapping;
- import org.springframework.Web.bind.annotation.RequestParam;
- import org.springframework.Web.bind.annotation.RestController;
- @RestController
- public class HelloController {
- @RequestMapping("/hello")
- public String hello(@RequestParam(value = "name") String name) {
- return "helle consul"+name;
- }
- }
- View Code
Consul 消费者
1. 引入依赖
在上面的基础上增加 feign 的引入
- <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.1.8.RELEASE</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
- <groupId>com.example</groupId>
- <artifactId>SpringCloudConsulConsumer</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>war</packaging>
- <name>SpringCloudConsulConsumer</name>
- <description>Demo project for Spring Boot</description>
- <properties>
- <java.version>1.8</java.version>
- <spring-cloud.version>Greenwich.SR2</spring-cloud.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-Web</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-all</artifactId>
- <version>2.1.3.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>com.ecwid.consul</groupId>
- <artifactId>consul-API</artifactId>
- <version>1.4.2</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-openfeign</artifactId>
- </dependency>
- <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-openfeign-core -->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-openfeign-core</artifactId>
- <version>2.1.2.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-tomcat</artifactId>
- <scope>provided</scope>
- </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>
- View Code
2. 配置文件
- spring.application.name=spring-cloud-consul-consumer
- server.port=8507
- spring.cloud.consul.host=127.0.0.1
- spring.cloud.consul.port=8500
- # 设置不需要注册到 consul 中
- spring.cloud.consul.discovery.register=false
- feign.hystrix.enabled=false
3. 增加注解
在 main 类中增加 @EnableFeignClients 注解
4. 参考 Eureka 中 feign 的调用
首先创建 HelloRemote 接口
- package com.example.demo;
- import org.springframework.cloud.openfeign.FeignClient;
- import org.springframework.Web.bind.annotation.RequestMapping;
- import org.springframework.Web.bind.annotation.RequestParam;
- @FeignClient(name= "consul-provider")
- public interface HelloRemote {
- @RequestMapping(value = "/hello")
- public String hello(@RequestParam(value = "name") String name);
- }
然后创建接口的实现
- package com.example.demo;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.Web.bind.annotation.RequestMapping;
- import org.springframework.Web.bind.annotation.RequestParam;
- import org.springframework.Web.bind.annotation.RestController;
- @RestController
- public class CallHelloController {
- @Autowired
- HelloRemote HelloRemote;
- @RequestMapping("/hello")
- public String index(@RequestParam String name) {
- return HelloRemote.hello(name);
- }
- }
- View Code
测试
依次启动 SpringCloudConsulProducer,SpringCloudConsulConsumer, 在浏览器输入 http://localhost:8507/hello?name=cuiyw
负载均衡
修改 SpringCloudConsulProducer 项目的端口, 在 HelloController 中修改 hello 方法以区分调用
- package com.example.demo;
- import org.springframework.Web.bind.annotation.RequestMapping;
- import org.springframework.Web.bind.annotation.RequestParam;
- import org.springframework.Web.bind.annotation.RestController;
- @RestController
- public class HelloController {
- @RequestMapping("/hello")
- public String hello(@RequestParam(value = "name") String name) {
- return "helle consul two"+name;
- }
- }
启动实例之后浏览器刷新 http://localhost:8507/hello?name=cuiyw , 可以看到下面两个响应内容, 从而实现负载均衡的效果.
参考: http://www.ityouknow.com/springcloud/2018/07/20/spring-cloud-consul.html
来源: https://www.cnblogs.com/5ishare/p/11595850.html