Spring Cloud Consul-学习笔记
Spring Cloud
微服务概念
微服务组件示意图
核心问题
- 服务很多客户端怎么访问
- 这么多服务如何通信
- 如何治理
- 服务崩溃怎么解决
注册中心
介绍
介你麻痹
学习顺序
CAP原则
A 可用性、C 一致性、P 分布式
Availability 可用性
Partition-Tolerance 分区容错性
Consistency 一致性
CP 效率低(牺牲可用性)
AP 牺牲一致性 (有脏数据)
CA 牺牲横向可扩容
对比
Consul 注册中心
介绍
调用方式
特性
Raft 算法
https://www.cnblogs.com/xybaby/p/10124083.html
与Paxos不同raft 算法主要应用于工程界
服务发现
健康发现
Key/Value 存储
多数据中心
支持http和dns协议接口
官方提供web管理界面
角色
- client: 客户端,无状态,将HTTP和DNS接口请求转发给局域网内的服务端集群
- server: 服务端,保存配置信息,高可用集群,每个配置数据中心的server数量推荐为3个或五个。
模式
dev
cluster client/server
工作原理
安装consul
从官网下载
拷贝到 D:\Program Files\consul中
创建 CONSUL_HOME 环境变量并且加入到PATH中
consul agent -dev -client=0.0.0.0
[命令] [角色 ] [模式] [有权的访问者]
查看localhost:8500
如果localhost:8500 无法访问端口占用,可以找个linxu启动
linxu
1
2
3sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install consul
Spring Cloud接入consul
创建 一个spring cloud项目
引入 pom
1
2
3
4
5<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
<version>3.0.4</version>
</dependency>yml配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27server:
port: ${SERVER_PORT:17180}
spring:
application:
name: consul-demo-service-product
cloud:
inetutils:
ignoredInterfaces: ['VMware.*','ingress'] # 必须过滤掉VMware 因为会豁达86.1
preferred-networks:
- ${NET_DOMAIN:192.168/16} #必须只选择192网段的否则会选择一些虚拟机网卡
consul:
host: localhost
port: 8500
discovery:
register: true
instance-id: ${spring.application.name}-${spring.cloud.client.hostname}-${server.port} # 必须加入名字和端口否则ID会相同
service-name: ${spring.application.name}
prefer-ip-address: true
# ip-address: ${spring.cloud.client.ip-address} #这里不能写会导致错误的IP
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
shutdown:
enabled: true该死的国外资料真TM好
写一个Product服务 要有端口信息
再写一个Order服务 并且调用自己ideProduct
在Order中通过RestTemplet调用。
集群案例
环境准备表
服务器IP | Consul类型 | NODE节点 |
---|---|---|
192.168.3.190 | server | server-01 |
192.168.3.191 | server | server-02 |
192.168.3.192 | server | server-03 |
192.168.3.148 | clinet | client-01 |
安装
1 | sudo yum install -y yum-utils |
网络下载太忙就到官方下载 x86的zip包
- zip安装
1 | unzip consul_1.10.3_linux_amd64.zip -d /usr/local/consul |
启动集群
1 | 关闭防火墙 |
参数含义:
-bootstrap-expect=3
: 表示至少三个节点-bind
:表示绑定的ip-server
:表示以服务端启动-ui
:带有web界面-data-dir
:数据存放地址-node
:服务名
查看集群成员
1 | C:\Users\dell> consul members |
docker环境无部署consul
搭建docker私有仓库
创建私有仓库
创建密码
1
2mkdir auth
docker run --entrypoint htpasswd httpd:2 -Bbn akachi TS8495877 > auth/htpasswd可能遇得到httpd:2下载不到的问题
参考以下解决问题
1
2
3
4
5
6
7
8
9
10
11
121、阿里云docker加速器配置文件
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://s796m7v3.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart dockeryml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18services:
registry:
image: registry:2.7.1
ports:
- 5000:5000
networks:
- registry
volumes:
- ./data:/var/lib/registry
- ./auth:/auth
mem_limit: 256m
restart: always
environment:
- "REGISTRY_AUTH=htpasswd"
- "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"
- "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd"
networks:
registry:登陆
1
docker login entry.akachi:5000
报错:
Error response from daemon: Get “https://192.168.3.140:5000/v2/": http: server gave HTTP response to HTTPS client
1
2
3
4
5
6
7
8
9
10
11
12sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://s796m7v3.mirror.aliyuncs.com"],
"insecure-registries": ["http://entry.akachi:5000"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker退出
1
docker logout entry.akachi:5000
考虑SSH的情况
看文档这里没试
创建ssh授权书
1
2mkdir -p certs
openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/entry.akachi.key -x509 -days 3000 -out certs/entry.akachi.crt配置域名为entry.akachi
在其他机器上使用DNS
在DNS上使用hosts配置
测试仓库是不是可用
1
2
3
4
5
6
7
8
9
10
11下载
docker pull ubuntu:16.04
改名
docker tag ubuntu:16.04 entry.akachi:5000/my-ubuntu
上传
docker push entry.akachi:5000/my-ubuntu
删除本地
docker rmi entry.akachi:5000/my-ubuntu
docker rmi ubuntu:16.04
下载
docker pull entry.akachi:5000/my-ubuntu好测试成功你可以继续玩乐
准备资料
官网docker:https://hub.docker.com/_/registry
文档中的关于密码创建的部分:https://docs.docker.com/registry/deploying/
-
这里有docker-compose.yml。我们只考虑密码和data。
-
参考在docker中设置环境变量:https://docs.docker.com/compose/environment-variables/
用k8s或者swarm的情境下不需要搭建consul
资料
看看人家的方案:https://segmentfault.com/a/1190000011009638
搭建无consul的微服务
DockerFile 在项目根目录上
1
2
3
4
5
6
7
8
9
10FROM openjdk:11-jre-slim
MAINTAINER akachi zsts@hotmail.com
WORKDIR /ROOT
COPY target/*.jar app.jar
COPY src/main/resources/application*.* .
ENV PROFILES_ACTIVE pro
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]打包命令
1
docker build -f DockerFile -t entry.akachi:5000/cloud-demo/product:1.0 .
运行命令测试
1
2docker run -d -p 17180:17180 entry.akachi:5000/cloud-demo/product:1.0
docker run -d -p 17280:17280 entry.akachi:5000/cloud-demo/order:1.0pull
1
docker pull entry.akachi:5000/cloud-demo/product:1.0
编写dcoker-compose.yml 在任何地方
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29version: "3.9"
services:
cloud-demo-order:
image: entry.akachi:5000/cloud-demo/order:1.0
deploy:
mode: replicated
replicas: 2
placement:
max_replicas_per_node: 1
environment: vip
PRODUCT_HOST: cloud-demo-product
ports:
- 17280:17280
networks:
- cloud-demo
cloud-demo-product:
image: entry.akachi:5000/cloud-demo/product:1.0
deploy:
mode: replicated
replicas: 4
placement:
max_replicas_per_node: 2
endpoint_mode: vip
ports:
- 17180:17180
networks:
- cloud-demo
networks:
cloud-demo:
Consul 配置中心
consul 特性
- raft 算法
- 服务发现
- 健康检查
- Key/Value 存储( 配置中心)
- 多数据中心
- 支持http和dns协议接口
- 官方提供Web管理界面
安装
注册中心讲过了
1 | unzip consul_1.10.3_linux_amd64.zip -d /usr/local/consul |
运行
1 | consul agent -dev -client=0.0.0.0 |
-dev 开发者模式
-client = 允许访问IP
创建资源文件夹
spring: https://docs.spring.io/spring-cloud-consul/docs/current/reference/html/#spring-cloud-consul-config
1
2
3
4config/testApp,dev/
config/testApp/
config/application,dev/
config/application/
初始化配置目录
- 创建 config/productService-dev和config/oracleService-dev
初始化项目
- product 和order 用consul 注册中心启动起来
项目中要导入的包介绍
- spring-boot-starter-actuator 监控管理时需要
- spring-cloud-starter-consul-discovery 用于发现服务-调用注册中心
- spring-cloud-starter-consul-config spring-bootstrap文件导入需要系统级的权限在2020.* 版本禁用乐 如果需要我们需要引入包
- spring-cloud-starter-consul-config 用于调用配置中心
- spring-boot-starter-web springweb
1 | <?xml version="1.0" encoding="UTF-8"?> |
在resources 目录中创建bootstrap.yml
参考cloud.spring-cloud
内容基本与application.yml一致
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39server:
port: ${SERVER_PORT:17180}
spring:
application:
name: consul-demo-service-product
profiles:
active: dev # 指定环境,默认加载 default环境也就是无配置信息
cloud:
inetutils:
ignoredInterfaces: [ 'VMware.*','ingress' ] # 必须过滤掉VMware 因为会豁达86.1
preferred-networks:
- ${NET_DOMAIN:192.168/16} #必须只选择192网段的否则会选择一些虚拟机网卡
consul:
host: ${CONSUL_HOST:localhost}
port: 8500
config: #使用consul配置中心
enabled: true
prefixes: [ "config" ] #路径
default-context: productService
profile-separator: '-' # 分隔符
format: yaml
data-key: appCconfig #文件名
watch: #检查更新
enabled: true
delay: 1000
discovery:
register: true
instance-id: ${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}} # 必须加入名字和端口否则ID会相同
service-name: ${spring.application.name}
prefer-ip-address: true
# ip-address: ${spring.cloud.client.ip-address} #这里不能写会导致错误的IP
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
shutdown:
enabled: true在consul上创建 appConfig
1
2
3
4
5
6name: order-service-dev
mysql:
host: localhost
port: 3306
username: root
password: root在项目内用注解加载配置
@Value(“${name}”)
加载单一配置项
@ConfigurationProperties(“mysql”)
加载配置对象下的所有属性到Class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22package org.akachi.eurekademo.product.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
/**
* @Author akachi
* @Email zsts@hotmail.com
* @Date 2021/11/3 17:24
*/
public class MySqlProperties {
private String host;
private Integer port;
private String username;
private String password;
}@RefreshScope 需要根据配置文件变化的类需要加入“刷新作用域”的注解
实际上我们可以只在启动配置中写入最少量的配置
bootstrap.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17spring:
profiles:
active: dev # 指定环境,默认加载 default环境也就是无配置信息
cloud:
consul:
host: ${CONSUL_HOST:localhost}
port: 8500
config: #使用consul配置中心
enabled: true
prefixes: ["config"]#路径
default-context: productService
profile-separator: '-' # 分隔符
format: yaml
data-key: appConfig #文件名
watch: #检查更新
enabled: true
delay: 1000/config/orderProduct-dev/appConfig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45name: product-dev
mysql:
username: root
password: root
port: 3306
host: localhost
server:
port: ${SERVER_PORT:17180}
spring:
application:
name: consul-demo-service-product
profiles:
active: dev # 指定环境,默认加载 default环境也就是无配置信息
cloud:
inetutils:
ignoredInterfaces: [ 'VMware.*','ingress' ] # 必须过滤掉VMware 因为会豁达86.1
preferred-networks:
- ${NET_DOMAIN:192.168/16} #必须只选择192网段的否则会选择一些虚拟机网卡
consul:
host: ${CONSUL_HOST:localhost}
port: 8500
config: #使用consul配置中心
enabled: true
prefixes: ["config"]#路径
default-context: productService
profile-separator: '-' # 分隔符
format: yaml
data-key: appConfig #文件名
watch: #检查更新
enabled: true
delay: 1000
discovery:
register: true
instance-id: ${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}} #必须加入名字和端口否则ID会相同
service-name: ${spring.application.name}
prefer-ip-address: true
# ip-address: ${spring.cloud.client.ip-address} #这里不能写会导致错误的IP
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
shutdown:
enabled: true
运行后测试是否成功访问就可以了profiles.active
如果为空则没有-dev 直接为orderService 目录
备份和还原数据
1 | 启动命令 |
dokcer环境部署全套 consul
问题1:
dockers环境弹性启动每个实例用的同一个yml所以很可能无法区分ID导致注册中心只知道一个实例
解决方案:
加入
$HOST_NAME
1
2 !/bin/sh
export HOST_NAME=`hostname`启动的时候加入一个环境变量$HOST_NAME
yml中加入环境变量
1
2
3
4 ${HOST_NAME} =
# 看你用什么注册中心了
${HOST_NAME} =确保在yml的instanceId中有consul.instance.hostname的属性
问题2
consul 的k/v没有版本控制。通过git2consul加入版本控制
问题3
怎么在docker swarm 上搭建consul 集群
问题素材:
取得容器IP
1
2
3
4
5
6
7
8
9
10
11
12
13
14 docker run --detach --name consul --hostname consul-server-1 progrium/consul
-server -bootstrap -ui-dir /ui
Get container ip for further interactions
CONSUL_IP=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' consul)
The container also runs a web UI at $CONSUL_IP:8500/ui
举个栗子 获得tomcatIP如下
docker inspect -f '{{ .NetworkSettings.Networks.tomcat01_default.IPAddress }}'
CONSUL_IP=$(docker inspect -f '{{ NetworkSettings.Networks.tomcat01_default.IPAddress }}' consul)
8eb571af2ac1
资源
spring: https://docs.spring.io/spring-cloud-consul/docs/current/reference/html/#spring-cloud-consul-config
搭建基于Docker Swarm 的 consul集群注册中心实战
准备
下载consul
windows 下载
https://www.consul.io/downloads
https://releases.hashicorp.com/consul/1.12.2/consul_1.12.2_windows_386.zip
consul docker
https://hub.docker.com/_/consul
参考
还有这个
https://blog.csdn.net/liushengit/article/details/118693363
融合两个内容我们编写出一个可以运行并自激活的
consul-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125version: '3.8'
services:
consul-server1:
image: consul
ports:
- 8510:8500
- 8310:8300
- 8311:8301
- 8312:8302
- 8610:8600
environment:
- CONSUL_BIND_INTERFACE=eth0
deploy:
mode: global
placement:
constraints:
- node.hostname == Docker-swarm-manager01
command: >
agent -server -ui
-node=consul-server1
-bootstrap-expect=3
-client=0.0.0.0
-retry-join=consul_consul-server2
-retry-join=consul_consul-server3
-retry-join=consul_consul-server4
-data-dir=/consul/data
-datacenter=dc1
volumes:
- /nfs/docker/volumes/consul/server1:/consul/data
networks:
consul-net:
consul-server2:
image: consul
ports:
- 8520:8500
- 8320:8300
- 8321:8301
- 8322:8302
- 8620:8600
environment:
- CONSUL_BIND_INTERFACE=eth0
deploy:
mode: global
placement:
constraints:
- node.hostname == Docker-swarm-manager02
command: >
agent -server -ui
-node=consul-server2
-bootstrap-expect=3
-client=0.0.0.0
-retry-join=consul_consul-server1
-retry-join=consul_consul-server3
-retry-join=consul_consul-server4
-data-dir=/consul/data
-datacenter=dc1
volumes:
- /nfs/docker/volumes/consul/server2:/consul/data
networks:
consul-net:
consul-server3:
image: consul
ports:
- 8530:8500
- 8330:8300
- 8331:8301
- 8332:8302
- 8630:8600
environment:
- CONSUL_BIND_INTERFACE=eth0
deploy:
mode: global
placement:
constraints:
- node.hostname == Docker-swarm-manager03
command: >
agent -server -ui
-node=consul-server3
-bootstrap-expect=3
-client=0.0.0.0
-retry-join=consul_consul-server1
-retry-join=consul_consul-server2
-retry-join=consul_consul-server4
-data-dir=/consul/data
-datacenter=dc1
volumes:
- /nfs/docker/volumes/consul/server3:/consul/data
networks:
consul-net:
consul-server4:
image: consul
ports:
- 8540:8500
- 8340:8300
- 8341:8301
- 8342:8302
- 8640:8600
environment:
- CONSUL_BIND_INTERFACE=eth0
deploy:
mode: global
placement:
constraints:
- node.hostname == Docker-swarm-worker04
command: >
agent -server -ui
-node=consul-server4
-bootstrap-expect=3
-client=0.0.0.0
-retry-join=consul_consul-server1
-retry-join=consul_consul-server2
-retry-join=consul_consul-server3
-data-dir=/consul/data
-datacenter=dc1
volumes:
- /nfs/docker/volumes/consul/server4:/consul/data
networks:
consul-net:
networks:
consul-net:
ipam:
driver: default
config:
- subnet: "192.168.87.0/24"
启动
在 docker swarm上启动服务端
首先在所有机器上(除非使用网络文件系统)创建相应的文件夹
/nfs/docker/volumes/consul/server3
执行
docker stack deploy -c consul-compose.yml
创建项目
pom.xml
需要引入的包
1 | <groupId>org.springframework.boot</groupId> |
YML及解读
基于consul搭建带openfegin的配置文件
这是client端口的,其他只会更加简单
1 | server: |
circuitbreaker不工作的关键异常
必须引入包resilience4j
1 | <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-circuitbreaker-resilience4j --> |
参考:
https://stackoverflow.com/questions/69524571/spring-cloud-openfeign-3-0-1-fallback-not-being-triggered
下次可以去:https://www.baeldung.com/ 上找例子
搭建client
创建两个client模式运行的consul,consul必须要能够相互连接的网络才可以使用。
1 | # 安装consul consul.io去安装 |
搭建服务端之前的不能用
由于我们需要测试集群,而集群而端口被docker swarm 更改过所以需要重新搭建集群在8500上
搭建四台服务器
1
2
3
4
5
6
7
8
9
10
11
12
13安装consul consul.io去安装
创建 consul目录
mkdir consul
在四台机器上创建data目录
cd consul
mkdir data
创建start.sh 并且写入一下内容
vi start.sh
consul agent -server -ui -node=server1 -bootstrap-expect=3 -client=0.0.0.0 -bind=192.168.2.50 -retry-join=192.168.2.51 -retry-join=192.168.2.52 -retry-join=192.168.2.53 -data-dir=/root/consul/data -datacenter=dc1 > consul.log &
consul agent -server -ui -node=server2 -bootstrap-expect=3 -client=0.0.0.0 -retry-join=192.168.2.50 -bind=192.168.2.51 -retry-join=192.168.2.52 -retry-join=192.168.2.53 -data-dir=/root/consul/data -datacenter=dc1 > consul.log &
consul agent -server -ui -node=server4 -bootstrap-expect=3 -client=0.0.0.0 -retry-join=192.168.2.50 -retry-join=192.168.2.51 -bind=192.168.2.52 -retry-join=192.168.2.53 -data-dir=/root/consul/data -datacenter=dc1 > consul.log &
consul agent -server -ui -node=server3 -bootstrap-expect=3 -client=0.0.0.0 -retry-join=192.168.2.50 -retry-join=192.168.2.51 -retry-join=192.168.2.52 -bind=192.168.2.53 -data-dir=/root/consul/data -datacenter=dc1 > consul.log &
./start.sh
创建docker
编写dockerfile
1
2
3
4
5
6
7
8
9
10FROM openjdk:11-jre-slim
MAINTAINER akachi zsts@hotmail.com
WORKDIR /ROOT
COPY target/*SNAPSHOT.jar app.jar
COPY src/main/resources/application*.properties .
ENV PROFILES_ACTIVE dev
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]构建
docker build -t [server]:[port]/[path]/[name]:[tag] .
上传
docker push [allname]:[tag]
加入stack
默认情况下调用docker stack deploy 只会更新用到的service,除非加入–prune 才会清理不存在的service
编写一个demo-stack.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60version: "3.8"
services:
demo-get:
image: 192.168.2.129:5000/clairvoyants/demo-get
environment:
- PROFILES_ACTIVE=dev
- CONSUL_HOST=demo-get-consul
ports:
- 19111:19111
depends_on:
- demo-get-consu
networks:
consul-net:
demo-get-consul:
image: consul
environment:
- CONSUL_BIND_INTERFACE=eth0
command: >
agent -ui
-node=demo-get-consul
-client=0.0.0.0
-retry-join=consul_consul-server1
-retry-join=consul_consul-server2
-retry-join=consul_consul-server3
-retry-join=consul_consul-server4
-data-dir=/consul/data
networks:
consul-net:
demo-source:
image: 192.168.2.129:5000/clairvoyants/demo-source
environment:
- PROFILES_ACTIVE=dev
- CONSUL_HOST=demo-source-consul
ports:
- 19101:19101
depends_on:
- demo-source-consul
networks:
consul-net:
demo-source-consul:
image: consul
environment:
- CONSUL_BIND_INTERFACE=eth0
command: >
agent -ui
-node=demo-source-consul
-client=0.0.0.0
-retry-join=consul_consul-server1
-retry-join=consul_consul-server2
-retry-join=consul_consul-server3
-retry-join=consul_consul-server4
-data-dir=/consul/data
networks:
consul-net:
networks:
consul-net:
ipam:
driver: default
config:
- subnet: "192.168.87.0/24"每个service都带有一个consul,为了方便,我还没搞明白怎么安装一个consul到JDK的docker中先这么用把。
启动 docker
docker stack deploy -c demo-compose.yml consul –with-registry-auth
–with-registry-auth 必须加否则不会down image