一、Consul概述 / Consul安装

  • Consul是什么

  Consul 是一套开源的分布式服务发现和配置管理系统,由HashiCorp公司用Go语音开发

  Consul是一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控)解决方案,它是一个一个分布式的,高度可用的系统,而且开发使用都很简便。它提供了一个功能齐全的控制平面,主要特点是:服务发现、健康检查、键值存储、安全服务通信、多数据中心。

  官网:https://www.consul.io/

  中文文档:https://www.springcloud.cc/spring-cloud-consul.html

  安装教程:https://learn.hashicorp.com/consul/getting-started/install.html

  配置文档:https://www.consul.io/docs/agent/options.html

  • Consul的几个概念

  

                            图片来自于consul官方文档

  我们只看数据中心1,可以看出consul的集群是由N个SERVER,加上M个CLIENT组成的。而不管是SERVER还是CLIENT,都是consul的一个节点,所有的服务都可以注册到这些节点上,正是通过这些节点实现服务注册信息的共享。除了这两个,还有一些小细节,一一简单介绍。

  CLIENT
  CLIENT表示consul的client模式,就是客户端模式。是consul节点的一种模式,这种模式下,所有注册到当前节点的服务会被转发到SERVER,本身是不持久化这些信息。

  SERVER
  SERVER表示consul的server模式,表明这个consul是个server,这种模式下,功能和CLIENT都一样,唯一不同的是,它会把所有的信息持久化的本地,这样遇到故障,信息是可以被保留的。

  SERVER-LEADER
  中间那个SERVER下面有LEADER的字眼,表明这个SERVER是它们的老大,它和其它SERVER不一样的一点是,它需要负责同步注册的信息给其它的SERVER,同时也要负责各个节点的健康监测。
  其它信息其它信息包括它们之间的通信方式,还有一些协议信息,算法。它们是用于保证节点之间的数据同步,实时性要求等等一系列集群问题的解决。官方文档(https://www.consul.io/docs/internals/index.html)。

  • 安装Consul

  环境:CentOS 8.0

  1、下载二进制包

    命令:wget https://releases.hashicorp.com/consul/1.8.0/consul_1.8.0_linux_amd64.zip

  2、解压安装包
    unzip consul_1.8.0_linux_amd64.zip

  3、删除压缩包
    rm consul_1.8.0_linux_amd64.zip

  4、创建data、log目录

    mkdir data

    mkdir log

  5、配置环境变量,编辑/etc/profile 文件,内容如下:

    编辑命令:vim /etc/profile 

export CONSUL_HOME=/data/soft/consul
export PATH=$CONSUL_HOME:$PATH

  6、使用环境变量配置生效

    命令:source /etc/profile 

  7、验证 Consul 安装是否成功

    命令:consul -v

  • 运行Agent

  安装Consul后必须运行Agent,可以选择服务器或客户端模式。每个数据中心至少有一个服务器(推荐3~5个服务器集群)。

  简单起见,先启动一个Agent的开发模式:

  前台启动命令:consul agent -dev

  后台启动命令:nohup consul agent -dev  > /dev/null 2>&1 &

  • 浏览器查看图形化界面

  关闭防火墙,使用Linux-ip:8500访问

 

 

 

  • Agent常用的参数

参数名称用途
-server 此标志用于控制代理是运行于服务器/客户端模式,每个 Consul 集群至少有一个服务器,正常情况下不超过5个,使用此标记的服务器参与 Raft一致性算法、选举等事务性工作
-client 表示 Consul 绑定客户端接口的IP地址,默认值为:127.0.0.1,当你有多块网卡的时候,最好指定IP地址,不要使用默认值
-bootstrap-expect 预期的服务器集群的数量,整数,如 -bootstrap-expect=3,表示集群服务器数量为3台,设置该参数后,Consul将等待指定数量的服务器全部加入集群可用后,才开始引导集群正式开始工作,此参数必须与 -server 一起使用
-data-dir 存储数据的目录,该目录在 Consul 程序重启后数据不会丢失,指定此目录时,应确保运行 Consul 程序的用户对该目录具有读写权限
-node 当前服务器在集群中的名称,该值在整个 Consul 集群中必须唯一,默认值为当前主机名称
-bind Consul 在当前服务器侦听的地址,如果您有多块网卡,请务必指定一个IP地址(IPv4/IPv6),默认值为:0.0.0.0,也可用使用[::]
-datacenter 代理服务器运行的数据中心的名称,同一个数据中心中的 Consul 节点必须位于同一个 LAN 网络上
-ui 启用当前服务器内部的 WebUI 服务器和控制台界面
-join 该参数指定当前服务器启动时,加入另外一个代理服务器的地址,在默认情况下,如果不指定该参数,则当前代理服务器不会加入任何节点。可以多次指定该参数,以加入多个代理服务器,
-retry-join 用途和 -join 一致,当第一次加入失败后进行重试,每次加入失败后等待时间为 30秒
-syslog 指定此标志意味着将记录 syslog,该参数在 Windows 平台不支持

 二、搭建以Consul为注册中心的简单项目

  • consul-provider-payment8005

    pom.xml

    <dependencies>

        <!--consul依赖包-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

    </dependencies>

    application.yml

# 端口
server:
  port: 8005

spring:
  application:
    name: cloud-payment-service
  cloud:
    consul:
      host: 192.168.186.128
      port: 8500
      discovery:
        # hostname: 127.0.0.1
        service-name: ${spring.application.name}

    PaymentController

 1 package com.sdkj.controller;
 2 
 3 import org.springframework.beans.factory.annotation.Value;
 4 import org.springframework.stereotype.Controller;
 5 import org.springframework.web.bind.annotation.RequestMapping;
 6 import org.springframework.web.bind.annotation.ResponseBody;
 7 
 8 import java.util.UUID;
 9 
10 /**
11  * @Author wangshuo
12  * @Date 2022/5/22, 11:08
13  * Please add a comment
14  */
15 @Controller
16 @RequestMapping(value = "/payment")
17 public class PaymentController {
18 
19     @Value("${server.port}")
20     private String port;
21 
22     @RequestMapping(value = "/getConsul")
23     @ResponseBody
24     public String getPort() {
25         return "server Port: " + port + UUID.randomUUID();
26     }
27 }
  • consul-consumer-order8006

    pom.xml

    <dependencies>

        <!--consul依赖包-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

    </dependencies>

    application.yml

# 端口
server:
  port: 8006

spring:
  application:
    name: cloud-order
  cloud:
    consul:
      host: 192.168.186.128
      port: 8500
      discovery:
        # hostname: 127.0.0.1
        service-name: ${spring.application.name}

    AppConfig

 1 package com.sdkj.config;
 2 
 3 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 4 import org.springframework.context.annotation.Bean;
 5 import org.springframework.context.annotation.Configuration;
 6 import org.springframework.web.client.RestTemplate;
 7 
 8 /**
 9  * @Author wangshuo
10  * @Date 2022/5/22, 11:20
11  * Please add a comment
12  */
13 @Configuration
14 public class AppConfig {
15 
16     /**
17      * 注入restTemplate,请用请求rest接口
18      * @return
19      */
20     @Bean
21     // 标注此注解后,RestTemplate就具有了客户端负载均衡能力
22     // 负载均衡技术依赖于的是Ribbon组件~
23     // RestTemplate都塞入一个loadBalancerInterceptor 让其具备有负载均衡的能力
24     @LoadBalanced
25     public RestTemplate restTemplate(){
26         return new RestTemplate();
27     }
28 }

    OrderController

 1 package com.sdkj.controller;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.stereotype.Controller;
 5 import org.springframework.web.bind.annotation.RequestMapping;
 6 import org.springframework.web.bind.annotation.ResponseBody;
 7 import org.springframework.web.client.RestTemplate;
 8 
 9 /**
10  * @Author wangshuo
11  * @Date 2022/5/22, 11:20
12  * Please add a comment
13  */
14 @Controller
15 @RequestMapping(value = "/order")
16 public class OrderController {
17 
18     private static final String url = "http://cloud-payment-service";
19     @Autowired
20     RestTemplate restTemplate;
21 
22     @RequestMapping(value = "/getPaymentPort")
23     @ResponseBody
24     public String getUrl() {
25         return restTemplate.getForObject(url + "/payment/getConsul", String.class);
26     }
27 }