Consul
1 简介
Consul 官方站点:https://www.consul.io/
官方介绍是:Consul 是一种服务网格的解决方案,在 Consul 中,提供了服务发现、配置、分段等控制管理平台,Consul 中的每项功能都可以单独使用,也可以一起使用来构建完整的服务网格;在 Consul 内部,有一个简单的代理服务,所以在安装 Consul 后,马上就可以开始使用 Consul ;当然,Consul 也支持集成第三方代理,比如 Envoy。
Consul 是一个服务组件,在用户下载 Consul 的安装包后,可以立即运行它,或者通过其它托管程序运行它,Consul 只有一个程序包,无需另行安装;当运行 Consul 的时候,需要为其指定一些必须的参数,以供 Consul 在运行时使用;(比如参数 -data-dir 表示指定 Consul 存放数据的目录)。
我们不整那些服务网格之类的概念,
简单说,Consul在整个微服务架构体系里面就是起了注册中心和配置中心的作用。
服务注册
Consul 内部侦听 8500 端口,提供给 Consul 的客户端注册服务,比如张三开发了一个购物车程序,该购物车程序包含了“加入购物车”、“清空购物车” 两个接口,张三在开发购物车程序的时候,使用了 Consul 的客户端包组件,在程序运行起来以后,购物车程序就自动的连接到 Consul 的 8500 端口,注册了一个服务,该服务被命名为“购物车程序”,此时,Consul 并不知道 “购物车程序”有多少个接口,Consul 只知道 “购物车程序”的服务地址、端口。
服务发现
在“购物车程序”注册到 Consul 后,Consul 也仅仅知道有这么一个服务注册进来了,并且还配置了健康检查, Consul 会定时的去连接 “购物车程序”,确保其还处于可提供服务的状态,任何人(程序)都可以通过 Consul 的外部地址访问 Consul 内部的已注册的服务列表,从而获得真实的服务地址,然后调用该真实地址,获得结果。
键值存储(常常用作统一配置)
在 Consul 内部,提供了简单的数据存储,也就是 key/value 系统,kv 系统非常强大,它的作用包括允许节点动态修改配置、执行 leader 选举、服务发现、集成健康检查、或者其它你想要存储到 Consul 中的内容。
2 安装-windows系统
地址:https://www.consul.io/downloads.html
解压zip包,有一个consul.exe文件
执行 .\consul.exe ,看到如下输出,即安装成功。
执行.\consul.exe agent -dev 启动服务,看到如下,即启动成功
访问 ip:8500,可看到如下控制台页面
3 服务注册
创建springboot项目
映入consul相关依赖
<!--健康检查依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--consul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
配置文件
server:
port: 8000
spring:
cloud:
consul:
host: ip #consul服务器地址
port: 8500 #默认端口号8500
discovery:
instance-id: consul-client-8000
service-name: cuixk-${spring.application.name}
port: 8000
health-check-url: http://${spring.cloud.client.ip-address}:${server.port}/actuator/health #心跳检测地址
application:
name: consul-client
启动类添加@EnableDiscoveryClient
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient //开启服务发现、注册
public class ConsulClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConsulClientApplication.class, args);
}
}
启动服务,查看consul控制台,如下所示即注册成功
完整pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http:///POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http:///POM/4.0.0 https:///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.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cuixk.microservice.consul</groupId>
<artifactId>consul-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consul-client</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.0</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
4 服务注册、发现测试整合open-feign
由第三步,创建两个springboot项目,cuixk-consul-client、cuixk-consul-consumer
均注册到consul服务
consumer添加open-feign依赖,并在启动类上添加注解@EnableFeignClients 开启feign
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>xxxxx</version>
</dependency>
controller
@RestController
@RequestMapping("/get")
public class OrderController {
@Resource
private LoadBalancerClient loadBalancerClient;
@Resource
private UserFeign userFeign;
@GetMapping("/{id}")
public String getUserInfo(@PathVariable Integer id) {
User userInfo = userFeign.getUserInfo(id);
return userInfo.toString();
}
}
pojo user
@Data
public class User {
private Integer id;
private String name;
private Integer age;
}
feign
@FeignClient("cuixk-consul-client")
public interface UserFeign {
@GetMapping("/user/{id}")
User getUserInfo(@PathVariable Integer id);
}
调用consumer,controller接口 查看返回结果是否正确
返回如下即配置成功
GET http://localhost:8001/get/1
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 33
Date: Tue, 26 Jan 2021 10:04:51 GMT
Keep-Alive: timeout=60
Connection: keep-alive
User(id=1, name=provider, age=25)
Response code: 200; Time: 25ms; Content length: 33 bytes
5 docker consul集群搭建
准备工作
创建consul文件夹,在consul下创建三个子文件docker-consul-1、docker-consul-2、docker-consul-3
在consul官网下载解压后的脚本文件 分别拷贝到consul、docker-consul-1、docker-consul-2、docker-consul-3四个文件夹内。
用处:
consul 文件夹下脚本 的用来启动一个consul-client,因为通常一个服务都会再本地搭建一个 consul client节点服务作为consul代理 提供给SpringBoot服务节点用来绑定链接。
其余三个文件用于docker 挂载,启动三个consul-server节点
启动docker 容器
docker run -it -p 9501:8500 --name server_1 -v /root/consul/docker-consul-1:/home --privileged=true 300e315adb2f /bin/bash
--name 指定容器名 -p 9501:8500 端口号映射 -v 目录挂载
执行上述命令后,会进入容器控制台
cd /home 进入/home目录,可以看到consul脚本
[root@d2999f291692 /]# cd home
[root@d2999f291692 home]# ls
consul
使用chmod +x consul 给脚本赋权限
使用ip addr 查看ip 172.17.0.8
[root@d2999f291692 home]# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 59: eth0@if60: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:08 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.8/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever
启动consul
./consul agent -server -bootstrap-expect 2 -data-dir /etc/consul.d -node=server-1 -bind=172.17.0.8 -datacenter=dc -ui -client=0.0.0.0 &
-server 表示为consul服务节点
-bootstrap-expext 2 表示集群中至少有2台节点正常当前节点则可以正常工作。
data-dir 当前节点的数据存放位置
-node 表示当前节点名称
-bind 为当前容器环境的ip地址
-datacenter为节点的数据中心
-client为可以访问当前节点的ip信息 0.0.0.0 表示所有
& 表示后台运行。
如法炮制,启动server-2
docker run -it -p 9502:8500 --name server_2 -v /root/consul/docker-consul-2:/home --privileged=true 300e315adb2f /bin/bash
./consul agent -server -bootstrap-expect 2 -data-dir /etc/consul.d -node=server-2 -bind=172.17.0.9 -datacenter=dc -ui -client=0.0.0.0 &
启动server-3
docker run -it -p 9503:8500 --name server_3 -v /root/consul/docker-consul-3:/home --privileged=true 300e315adb2f /bin/bash
./consul agent -server -bootstrap-expect 2 -data-dir /etc/consul.d -node=server-3 -bind=172.17.0.10 -datacenter=dc -ui -client=0.0.0.0 &
将三台容器中不同的consul 服务节点添加到一个集群当中
进入server-2容器,server-3容器 执行命令 ./consul join 172.17.0.8
将 172.17.0.9 、172.17.0.10 节点加入到 172.17.0.8 节点集群中,当前没有集群,加入后 当前两个节点则会进行组成集群,并开始选举。
访问任一服务节点 ip:9501查看服务台,下图所示搭建成功
启动consul-client
启动在consul 文件夹下
./consul agent -client=0.0.0.0 -data-dir /etc/consul.d -datacenter=dc-bind=172.17.0.1 -node=client-1
springboot项目 由第4节 测试,连接到client的ip 端口号,启动服务,查看任一服务控制台
调用接口能否成功,有返回则集群可用
6 问题记录
5.1 启动异常
Caused by: java.lang.IllegalArgumentException: Consul service ids must not be empty, must start with a letter, end with a letter or digit, and have as interior characters only letters, digits, and hyphen: 8000
由报错可知未配置 consul service ids must not be empty。
查看官网
解决一:配置 spring.cloud.consul.instance-id
解决二:配置spring.application.name,配置server.port