当前位置: 代码迷 >> 综合 >> Consul + Spring-cloud 注册中心
  详细解决方案

Consul + Spring-cloud 注册中心

热度:67   发布时间:2024-01-04 20:57:28.0

1. Consul

? Consul 是一个分布式高可用的系统,Consul 包含了很多的组件,但是作为一个整体,为你的基础设施提供服务发现和服务配置的工具。

Consul 组件

1)服务器发现

? Consul的客户端空提供一个服务 , 比如 api 或者 MySQL,一些客户端可以使用 Consul 去发现一个指定服务的提供者,通过 DNS 或者 HTTP应用程序可用很容易的找到它所依赖的服务

2) 健康检查

? Consul 客户端可用提供任意数量的健康检查,指定一个服务或本地节点这个信息来监视集群的健康。

3)Key/Value存储

? 应用程序可根据自己需要使用Consul的层级的Key/value存储

4)多数据中心:

? Consul 支持开箱即用 的多数据中心,这意味着用户不需要担心需要建立额外的抽象让业务扩展到多个地区

2. consul 可以做spring-cloud-consul的注册中心

? 1) 微服务注册中心

? 2) 服务发现

? 3) 键值对存储, docker swarm 集群使用 consul

入手方向:

? consul 集群搭建

? consul 的常用指令

? consul 键值对存储如何存储

? consul + Nginx 实现微服务动态代理

? 动态代理: 传统NGinx通过 upstream 集群,location {proxy_pass }实现

? 动态,实现对微服务的状态感知,根据微服务的状态,动态对 upstream 进行伸缩

3. 搭建 consul 集群

? Consul 集群的每个节点都需要安装 Consul,且安装 java、maven环境

  • 实验环境

    • server1: 192.168.116.103 集群首领
    • server2:192.186.116.104
    • server3: 192.168.116.105 带有 ui 页面
    • Client: 192.168.116.106

1) 部署 Consul 环境(每台操作)

[root@localhost ~]# unzip consul_1.4.0_linux_amd64.zip -d /usr/local/sbin/
Archive:  consul_1.4.0_linux_amd64.zipinflating: /usr/local/sbin/consul  
[root@localhost ~]# consul -v
Consul v1.4.0
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)

默认端口 8500

  • 创建所需的文件目录
[root@localhost ~]# mkdir -p /opt/consul/{data,config,logs}

2) 创建集群(首领)

[root@localhost ~]# consul agent -server -node=consul1 -bootstrap-expect 2 \
-data-dir /opt/consul/data/ -config-dir /opt/consul/config/ \
-bind 192.168.116.103 -client 0.0.0.0 \
-enable-script-checks=true -datacenter=cjk01

? 报错:

? 以下报错表示找不到 leader 首领,并不碍事,需要要再将一台consul加入集群内即可

	    2020/02/27 08:50:45 [ERR] agent: failed to sync remote state: No cluster leader
2020/02/27 08:50:51 [ERR] agent: Coordinate update error: No cluster leader
  • 参数解释
consul agent 							# 启动一个代理-server   								# 以服务端的形式来启动,如不添加则表示为 client-node=consul1							# 当前节点在集群中的 名称-bootstrap-expect 2						# 集群的最小节点数量-data-dir								# 数据存放目录-config-dir								# 配置文件存放目录-bind 									# 指定当前consul绑定 IP地址 -client	0.0.0.0							# 允许访问地址,表示允许所有人访问-enable-script-checks=true				 # 开启心跳检测-datacenter=cjk01						# 数据中心名称,类似于数据库,不同的数据中心代表不同的 集群-join 192.168.116.103					 # 指定集群首领IP地址-ui 									# 添加 ui 界面

3)部署 server2

  • 绑定自身的IP地址
[root@localhost ~]# consul agent -server -node=consul2 \-data-dir /opt/consul/data -config-dir /opt/consul/config/ \-bind 192.168.116.104 -client 0.0.0.0 \-enable-script-checks=true -datacenter=cjk01 \-join 192.168.116.103

4) 部署 server3

  • 添加 ui 界面
[root@localhost ~]# consul agent -server -node=consul3 \
-data-dir /opt/consul/data -config-dir /opt/consul/config/ \
-bind 192.168.116.105 -client 0.0.0.0 \
-enable-script-checks=true -datacenter=cjk01 \
-join 192.168.116.103 -ui# 加入 ui 可以查看 集群 web界面
  • 查看集群成员状态
    • ? 在群集内任意一台查看都可以,包括服务端与客户端
[root@localhost ~]# consul members
Node     Address               Status  Type    Build  Protocol  DC     Segment
consul1  192.168.116.103:8301  alive   server  1.4.0  2         cjk01  <all>
consul2  192.168.116.104:8301  alive   server  1.4.0  2         cjk01  <all>
consul3  192.168.116.105:8301  alive   server  1.4.0  2         cjk01  <all>

5) 部署 client

? 不添加 -server 为 client

[root@localhost ~]# consul agent -node=client \
-data-dir /opt/consul/data -config-dir /opt/consul/config/ \
-bind 192.168.116.106 -client 0.0.0.0 \
-enable-script-checks=true -datacenter=cjk01 \
-join 192.168.116.103
  • 再次查看状态
[root@localhost ~]# consul members
Node     Address               Status  Type    Build  Protocol  DC     Segment
consul1  192.168.116.103:8301  alive   server  1.4.0  2         cjk01  <all>
consul2  192.168.116.104:8301  alive   server  1.4.0  2         cjk01  <all>
consul3  192.168.116.105:8301  alive   server  1.4.0  2         cjk01  <all>
client   192.168.116.106:8301  alive   client  1.4.0  2         cjk01  <default>
如何区分 是否为 服务端

? 启动如果带有 -serve为服务端

? 启动不带有 -server 为 客户端

4. 通过网页查看信息

  • 查看节点的集群大哥

    • http://ip:8500/v1/status/leader
[root@localhost ~]# curl http://192.168.116.104:8500/v1/status/leader
"192.168.116.103:8300"
  • 查看节点详细信息

[root@localhost ~]# curl http://192.168.116.103:8500/v1/catalog/nodes?		\ # 以上方式显示出来,则是乱糟糟的,需要使用 ?pretty 美化输出[root@localhost ~]# curl http://192.168.116.103:8500/v1/catalog/nodes?pretty?	PS: ?pretty 美化输出
  • 查看注册中心所注册的服务

[root@localhost ~]# curl http://192.168.116.103:8500/v1/catalog/services
{
    "consul":[]}
  • 查看具体服务信息

    [root@localhost ~]# curl http://192.168.116.103:8500/v1/catalog/services/producer
    
  • 查看集群的成员

    • /status/peers 查看集群server成员
[root@localhost ~]# curl http://192.168.116.103:8500/v1/status/peers
["192.168.116.103:8300","192.168.116.104:8300","192.168.116.105:8300"]
  • 进入集群 ui界面

    • 通过 ui 界面可以检查集群节点信息,并对其添加键值对
    http://192.168.116.105:8500/ui/cjk01/services

5. 键值对

consul agent 对consul 实例进行操作,多只创建集群或添加节点

consul kv 对键值对进行操作,例如: 数据存储

1) 创建或者更新( put)

  • 格式

    consul  kv  put  key  avlue
    
  • 创建文件形式的键值对

    [root@localhost ~]# consul kv put redis/config/connection 10
    Success! Data written to: redis/config/connection
    
  • 创建 键值对

    [root@localhost ~]# consul kv put aaa 111
    Success! Data written to: aaa
    

2) 获取值 (get)

  • 格式

    consul  kv  get   key
    
  • 查看键值

[root@localhost ~]# consul kv get redis/config/connection
10
[root@localhost ~]# consul kv get aaa
111

3) 查询详情 (detailed)

  • 格式

    consul  kv  get  -datailed  key
    
  • 查看一个键值对的详细信息

[root@localhost ~]# consul kv get -detailed redis/config/connection
CreateIndex      2836
Flags            0
Key              redis/config/connection
LockIndex        0
ModifyIndex      2836
Session          -
Value            10[root@localhost ~]# consul kv get -detailed aaa
CreateIndex      564
Flags            0
Key              aaa
LockIndex        0
ModifyIndex      2852
Session          -
Value            111

4) 删除键 (delete)

  • 格式

    consul  kv   delete   key
    
[root@localhost ~]# consul kv delete redis/config/connection
Success! Deleted key: redis/config/connection[root@localhost ~]# consul kv delete aaa
Success! Deleted key: aaa[root@localhost ~]# consul kv get redis/config/connection
Error! No key exists at: redis/config/connection[root@localhost ~]# consul kv get aaa
Error! No key exists at: aaa

5) 递归删除 (recurse)

  • 格式
consul kv delete -recurse
# 创建 key
[root@localhost ~]# consul kv put redis/one 1
Success! Data written to: one
[root@localhost ~]# consul kv put redis/two 2
Success! Data written to: two
[root@localhost ~]# consul kv put redis/three 3
Success! Data written to: three
[root@localhost ~]# consul kv put redis/four 4
Success! Data written to: four# 递归删除,删除整个目录内容[root@localhost ~]# consul kv delete -recurse redis/
Success! Deleted keys with prefix: redis/# 再次查看
[root@localhost ~]# consul kv get redis/three 
Error! No key exists at: redis/three

6) 导出指定前缀的键 ( export)

  • 格式
consul  kv  export  keys
[root@localhost ~]# consul kv put redis/one 1
Success! Data written to: redis/one
[root@localhost ~]# consul kv put redis/two 2
Success! Data written to: redis/two
[root@localhost ~]# consul kv put redis/three 3
Success! Data written to: redis/three
[root@localhost ~]# consul kv put redis/four 4
Success! Data written to: redis/four[root@localhost ~]# consul kv export redis/
[{
    "key": "redis/four","flags": 0,"value": "NA=="},{
    "key": "redis/one","flags": 0,"value": "MQ=="},{
    "key": "redis/three","flags": 0,"value": "Mw=="},{
    "key": "redis/two","flags": 0,"value": "Mg=="}
]

7) 列出指定前缀的所有键 (keys)

  • 格式
consul  kv  get  -keys  keys
[root@localhost ~]# consul kv put redis1 1
Success! Data written to: redis1[root@localhost ~]# consul kv get -keys redis
redis/
redis1[root@localhost ~]# consul kv get -keys redis/
redis/four
redis/one
redis/three
redis/two# -seperator="" 表示禁用分隔符 / 
[root@localhost ~]# consul kv get -keys -separator="" redis
redis/four
redis/one
redis/three
redis/two
redis1

8) 列出所有的键

[root@localhost ~]# consul kv get -keys 
four
one
redis/
redis1
three
two

6. consul+spring-cloud 实现服务架构

  • consul 做注册中心

? 生产者: 192.168.116.103:8501

? 生产者2: 192.168.116.104:8502

? 注册中心: 192.168.116.105:8500

? 消费者: 192.168.116.106:8503

  • 集群内 所有的server节点,都可以是 注册中心

? 拉入 Spring-cloud 代码(1、2、4)

	[root@localhost ~]# git clone https://github.com/luojunyong/spring-cloud-examples.git

1) 部署生产者

  • spring-cloud-consul-producer 为 consul的生产者
[root@localhost ~]# git clone https://github.com/luojunyong/spring-cloud-examples.git 
[root@localhost ~]# cd spring-cloud-examples/spring-cloud-consul/spring-cloud-consul-producer[root@localhost spring-cloud-consul-producer]# vim src/main/resources/application.properties spring.application.name=spring-cloud-consul-producer
server.port=8501								# 运行端口
spring.cloud.consul.host=192.168.116.105			# 指定注册中心的地址
spring.cloud.consul.port=8500						# 指定 注册中心的端口
#\u6CE8\u518C\u5230consul\u7684\u670D\u52A1\u540D\u79F0
spring.cloud.consul.discovery.serviceName=service-producer		# 服务名称
  • 运行代码
 [root@localhost spring-cloud-consul-producer]# mvn spring-boot:run

2) 部署生产者

  • spring-cloud-consul-producer-2 为生产者2
[root@localhost ~]# git clone https://github.com/luojunyong/spring-cloud-examples.git
[root@localhost ~]# cd spring-cloud-examples/spring-cloud-consul/spring-cloud-consul-producer-2/
[root@localhost spring-cloud-consul-producer-2]# vim src//main/resources/application.propertiesspring.application.name=spring-cloud-consul-producer
server.port=8502							# 运行代码
spring.cloud.consul.host=192.168.116.105		# 指定注册中心的地址
spring.cloud.consul.port=8500					# 指定注册中心的端口
#\u6CE8\u518C\u5230consul\u7684\u670D\u52A1\u540D\u79F0
spring.cloud.consul.discovery.serviceName=service-producer 	# 服务名称
  • 运行代码
[root@localhost spring-cloud-consul-producer-2]# mvn spring-boot:run
  • 可通过 web ui 界面查看注册中心内容

    http://192.168.116.105:8500/ui # 访问带有ui的consul

3) 部署 消费者

[root@localhost ~]# git clone https://github.com/luojunyong/spring-cloud-examples.git
[root@localhost ~]# cd spring-cloud-examples/spring-cloud-consul/spring-cloud-consul-consumer/
[root@localhost spring-cloud-consul-consumer]# vim src/main/resources/application.properties spring.application.name=spring-cloud-consul-consumer
server.port=8503			# 运行端口
spring.cloud.consul.host=192.168.116.103		# 指定注册中心地址
spring.cloud.consul.port=8500					# 指定注册中心端口
#\u8BBE\u7F6E\u4E0D\u9700\u8981\u6CE8\u518C\u5230consul\u4E2D
spring.cloud.consul.discovery.register=false	
  • 运行代码
[root@localhost spring-cloud-consul-consumer]# mvn spring-boot:run

4) 测试(访问 消费者)

? 可实现轮询的效果

[root@localhost ~]# curl http://192.168.116.106:8503/call
helle consul
[root@localhost ~]# curl http://192.168.116.106:8503/call
helle consul two

7. consul-template + Nginx + spring-cloud 实现动态轮询

通过 consul-templayte 与 Nginx实现动态轮询

通过注册中心获取到生产者的地址与端口,写入配置文件内,并将其读取至nginx配置文件中实现动态轮询

1) 安装 consul-template 工具

[root@localhost ~]# tar -zxf consul-template_0.19.5_linux_amd64.tgz -C /usr/local/sbin/

2) 安装 Nginx

[root@localhost ~]# tar -zxf nginx-1.12.2.tar.gz -C /usr/src/
[root@localhost ~]# cd /usr/src/nginx-1.12.2/
[root@localhost nginx-1.12.2]# yum -y install pcre-devel openssl-devel
[root@localhost nginx-1.12.2]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --with-pcre && make && make install
[root@localhost nginx-1.12.2]# ln -s /usr/local/nginx/sbin/nginx /usr/local/nginx/

3) 创建 动态轮序获取模板

? [root@localhost ~]# vim /opt/consul/config/nginx-template.ctmp1

upstream web1 {
    ip_hash;{
    {
     range service "service-producer"}}server {
    {
    .Address}}:{
    {
    .Port}} max_fails=2 fail_timeout=30s;{
    {
    end}}
}
server {
    listen 80;server_name web1.consul.com;location \ {
    proxy_connect_timeout 900s;proxy_send_timeout    900s;proxy_read_timeout    900s;proxy_buffer_size      32k;proxy_buffers        4 32k;proxy_busy_buffers_size 64k;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://web1;}
}
  • 翻译

    upstream web1 {
          						# 负载均衡模块ip_hash;					# 调度算法{
          {
           range service "service-producer"}}		# 指定获取服务的名称server {
          {
          .Address}}:{
          {
          .Port}} max_fails=2 fail_timeout=30s;		# 通过变量获取 ip与端口{
          {
          end}}
    }
    server {
          listen 80;						# 监听端口server_name web1.consul.com;		# 监听地址location / {
          proxy_connect_timeout 900s;				# 连接代理服务超时时间proxy_send_timeout    900s;				# 接收代理服务器的超时时间proxy_read_timeout    900s;				# 连接成功后,等待响应时间proxy_buffer_size      32k;				# 一次接收多少数据proxy_buffers        4 32k;				# 将响应消息放入缓冲区proxy_busy_buffers_size 64k;			# 缓冲区大小proxy_set_header Host $host;			# 设定主机头proxy_set_header X-Real-IP $remote_addr;	# 扩展头部proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;	# 主体proxy_pass http://web1;					# 指定后端服务器集群}
    }
    
    • 测试模板

      测试模板是否能够获取到注册中心地址服务

[root@localhost ~]# consul-template -consul-addr 192.168.116.105:8500 -template /opt/consul/config/nginx-template.ctmp1:/usr/local/nginx/conf/vhost/web1.conf:"nginx -s relod" -dry# consul-template 命令字# -consul-addr 指定注册中心地址# -template 指定模板位置# :/usr/**** 生成新的配置文件位置(目录需要创建)# :'nginx -s reload' 生成后执行该命令# -dry 只执行命令,不生成配置文件> /usr/local/nginx/conf/vhost/web1.conf
> upstream web1 {
    
> ip_hash;server 192.168.116.103:8501 max_fails=2 fail_timeout=30s;server 192.168.116.104:8502 max_fails=2 fail_timeout=30s;}server {
    listen 80;server_name web1.consul.com;location / {
    proxy_connect_timeout 900s;proxy_send_timeout    900s;proxy_read_timeout    900s;proxy_buffer_size     32k;proxy_buffers	    4 32k;proxy_busy_buffers_size 64k;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://web1;}}

4) 在 nginx 配置文件中插入该模板

  • 读取指定位置的配置文件,并将该文件中的 内容 加载至 nginx.conf中
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf# 在 http{ 添加 server{...}}?    include /usr/local/nginx/conf/vhost/*.conf;

5) 生成配置文件并生成 log日志文件

  • 向 注册中心获取变量后,生成新的配置文件,并执行 nginx 重载
  • 然后生成 log 日志文件,并在后再运行
[root@localhost ~]# consul-template -consul-addr 192.168.116.105:8500 -template /opt/consul/config/nginx-template.ctmp1:/usr/local/nginx/conf/vhost/web1.conf:"nginx -s reload" --log-level=info > /opt/consul/logs/consul-nginx.log 2>&1 &
  • 参数解释
--log-level=info 					# 生成日志文件> /opt/consul/logs/consul-nginx.log		# 将日志的标准输出至指定的文件2>&1								# 将日志的错误信息转换为标准信息输出至指定的文件& 						#将其转入后台进行运行
  • 查看以上命令是否在后台运行
[root@localhost ~]# ps -elf | grep -v grep | grep consul # 可使用 该命令查看是否在

6) 测试

  • 动态查看 logs 配置文件,用与监控日志内容
[root@localhost ~]# tail -f /opt/consul/logs/consul-nginx.log 
-	查看vhost  web1.conf 文件,查看当前所代理的服务器有哪些
	[root@localhost ~]# cat /usr/local/nginx/conf/vhost/web1.conf upstream web1 {
    ip_hash;server 192.168.116.103:8501 max_fails=2 fail_timeout=30s;server 192.168.116.104:8502 max_fails=2 fail_timeout=30s;}……………………
	-	通过上图我们可以看出,当前所代理的服务器,均为 注册中心所注册的 生产者服务器。

? 为了测试 动态代理的 弹性 伸缩性,我们将启动一台生产者 stop ,再次查看

? 此时的日志内容

2020/02/28 02:20:32.170629 [INFO] (runner) rendered "/opt/consul/config/nginx-template.ctmp1" => "/usr/local/nginx/conf/vhost/web1.conf"		# 重新成了新的没有办法2020/02/28 02:20:32.170807 [INFO] (runner) executing command "nginx -s reload" from    "/opt/consul/config/nginx-template.ctmp1" => "/usr/local/nginx/conf/vhost/web1.conf"		# 传输完 模板执行了 重载命令
2020/02/28 02:20:32.170931 [INFO] (child) spawning: nginx -s reload# 并且执行了 nginx -s reload 重载nginx
  • 此时查看 配置文件,可以很清楚的看出,只剩下了一个 生产者
[root@localhost ~]# cat /usr/local/nginx/conf/vhost/web1.conf 
upstream web1 {
    ip_hash;server 192.168.116.103:8501 max_fails=2 fail_timeout=30s;}……
  • ? 此时将 生产者 2 再次运行,并查看配置文件是否有改动
[root@localhost ~]# cat /usr/local/nginx/conf/vhost/web1.conf 
upstream web1 {
    ip_hash;server 192.168.116.103:8501 max_fails=2 fail_timeout=30s;server 192.168.116.104:8502 max_fails=2 fail_timeout=30s;}
…………
  • 测试 192.168.116.106/hello

[root@localhost ~]# curl 192.168.116.106/hello
helle consul two[root@localhost ~]# curl 192.168.116.106/hello
helle consul two
  相关解决方案