Consul注册中心

1.理解Consul

Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其它分布式

服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value 存储、多数据中心方案,不再需要依赖其它工具(比如 ZooKeeper 等),使用起来也较为简单。

Consul 使用 Go 语言编写,因此具有天然可移植性(支持Linux、Windows 和 Mac OS);安装包仅包含一个可执行文件,方便部署,与 Docker 等轻量级容器可无缝配合。

2.Consul特性
  • 算法服务发现
  • 健康检查
  • Key/Value 存储多数据
  • 中心
  • 支持 http 和 dns 协议接口官方
  • 提供 web 管理界面
3.Consul角色

client:客户端,无状态,将 HTTP 和 DNS 接口请求转发给局域网内的服务端集群。

server:服务端,保存配置信息,高可用集群,每个数据中心的 server 数量推荐为 3 个或者 5 个。

4.Consul工作原理

在这里插入图片描述

服务发现以及注册

当服务 Producer 启动时,会将自己的 Ip/host 等信息通过发送请求告知 Consul,Consul 接收到 Producer 的注册信息后,每隔 10s(默认)会向 Producer 发送一个健康检查的请求,检验 Producer 是否健康。

服务调用

当 Consumer 请求 Product 时,会先从 Consul 中拿到存储 Product 服务的 IP 和 Port 的临时表(temp table),从temp table 表中任选一个· Producer 的 IP 和 Port, 然后根据这个 IP 和 Port,发送访问请求; temp table 表只包含通过了健康检查的 Producer 信息,并且每隔 10s(默认)更新。

5.Consul安装

Eureka 其实就是个 Servlet 程序,跑在 Servlet 容器中;Consul 则是用 go 语言编写的第三方工具需要单独安装使用。

下载:访问 Consul 官网: https://www.consul.io 下载 Consul 的最新版本。

**安装:**单节点我们在 Windows 安装,集群环境在Linux 安装

单节点

cd 到对应的目录下,使用 cmd 启动 Consul

#-dev 表示开发模式运行 ,另外还有-server 表示服务模式运行
consul agent -dev -client=0.0.0.0

为了方便启动,也可以在 consul.exe 同级目录下创建一个脚本来启动,脚本内容如下:

consul agent -dev -client=0.0.0.0
pause

访问:http://localhost:8500/

6.Consul案例
创建项目,创建一个pom父工程
添加依赖
 <!-- 继承 spring-boot-starter-parent 依赖 -->
    <!-- 使用继承方式,实现复用,符合继承的都可以被使用 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
    </parent>

    <!--
        集中定义依赖组件版本号,但不引入,
        在子工程中用到声明的依赖时,可以不加依赖的版本号,
        这样可以统一管理工程中用到的依赖版本
     -->
    <properties>
        <!-- Spring Cloud Hoxton.SR1 依赖 -->
        <spring-cloud.version>Hoxton.SR1</spring-cloud.version>
    </properties>

    <!-- 项目依赖管理 父项目只是声明依赖,子项目需要写明需要的依赖(可以省略版本信息) -->
    <dependencyManagement>
        <dependencies>
            <!-- spring cloud 依赖 -->
            <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>
服务提供者service-provider
创建项目
添加依赖
<!-- 继承父依赖 -->
    <parent>
        <groupId>com.shsxt</groupId>
        <artifactId>consul-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>

      <!-- netflix eureka client 依赖 -->
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-consul-discovery</artifactId>
      </dependency>
      <!-- spring boot actuator 依赖 -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-actuator</artifactId>
      </dependency>
      <!-- spring boot web 依赖 -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <!-- lombok 依赖 -->
      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <scope>provided</scope>
      </dependency>

      <!-- spring boot test 依赖 -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
          <exclusions>
              <exclusion>
                  <groupId>org.junit.vintage</groupId>
                  <artifactId>junit-vintage-engine</artifactId>
              </exclusion>
          </exclusions>
      </dependency>

配置文件
spring:
  application:
    name: service-provider # 应用名称
  # 配置 Consul 注册中心
  cloud:
    consul:
      # 注册中心的访问地址
      host: localhost
      port: 8500
      # 服务提供者信息
      discovery:
        register: true                                # 是否需要注册
        instance-id: ${spring.application.name}-01    # 注册实例 id(必须唯一)
        service-name: ${spring.application.name}      # 服务名称
        port: ${server.port}                          # 服务端口
        prefer-ip-address: true                       # 是否使用 ip 地址注册
        ip-address: ${spring.cloud.client.ip-address} # 服务请求 ip

# 端口
server:
  port: 8601

编写服务

User.java

package com.shsxt.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@NoArgsConstructor
//@AllArgsConstructor
public class User implements Serializable {

    private Integer id;
    private String username;
    private Integer age;

    public User(Integer id, String username, Integer age) {
        this.id = id;
        this.username = username;
        this.age = age;
    }
}

UserService.java

/**
 * 用户服务
 */
public interface UserService {

    /**
     * 查询用户列表
     *
     * @return
     */
    List<User> selectUserList();

}
/**
 * 用户服务
 */
@Service
public class UserServiceImpl implements UserService {

    /**
     * 查询用户列表
     *
     * @return
     */
    @Override
    public List<User> selectUserList() {
        return Arrays.asList(
                new User(1, "张三", 20),
                new User(2, "李四", 21),
                new User(3, "王五", 22)
        );
    }

}
控制层
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 查询用户列表
     *
     * @return
     */
    @GetMapping("/list")
    public List<User> selectUserList() {
        return userService.selectUserList();
    }

}
启动类
@SpringBootApplication
public class ServiceProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceProviderApplication.class, args);
    }

}

访问: http://localhost:8500/

服务消费者service-consumer
创建项目
添加依赖
 <!-- 继承父依赖 -->
    <parent>
        <groupId>com.shsxt</groupId>
        <artifactId>consul-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
      <!-- netflix eureka client 依赖 -->
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-consul-discovery</artifactId>
      </dependency>
      <!-- spring boot actuator 依赖 -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-actuator</artifactId>
      </dependency>
      <!-- spring boot web 依赖 -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <!-- lombok 依赖 -->
      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <scope>provided</scope>
      </dependency>

      <!-- spring boot test 依赖 -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
          <exclusions>
              <exclusion>
                  <groupId>org.junit.vintage</groupId>
                  <artifactId>junit-vintage-engine</artifactId>
              </exclusion>
          </exclusions>
      </dependency>
  </dependencies>
配置文件
spring:
  application:
    name: service-consumer # 应用名称
  # 配置 Consul 注册中心
  cloud:
    consul:
      # 注册中心的访问地址
      host: localhost
      port: 8500
      # 服务提供者信息
      discovery:
        register: false                               # 是否需要注册
        instance-id: ${spring.application.name}-01    # 注册实例 id(必须唯一)
        service-name: ${spring.application.name}      # 服务名称
        port: ${server.port}                          # 服务端口
        prefer-ip-address: true                       # 是否使用 ip 地址注册
        ip-address: ${spring.cloud.client.ip-address} # 服务请求 ip

# 端口
server:
  port: 8701

消费服务
package com.shsxt.pojo;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@NoArgsConstructor
//@AllArgsConstructor
public class User implements Serializable {

    private Integer id;
    private String username;
    private Integer age;

    public User(Integer id, String username, Integer age) {
        this.id = id;
        this.username = username;
        this.age = age;
    }
}
/**
 * 用户服务
 */
public interface UserService {


    /**
     * 查询用户列表
     *
     * @return
     */
    List<User> selectUserList();

}
/**
 * 用户服务
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 查询用户列表
     *
     * @return
     */
    @Override
    public List<User> selectUserList() {
        // ResponseEntity: 封装了返回数据
        ResponseEntity<List<User>> response = restTemplate.exchange(
                "http://service-provider/user/list",
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<User>>() {});
        return response.getBody();
    }
}
控制层
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 用户管理
     *
     * @return
     */
    @GetMapping("/manage")
    public List<User> userManage() {
        return userService.selectUserList();
    }

}
启动类
@SpringBootApplication
public class ServiceConsumerApplication {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(ServiceConsumerApplication.class, args);
    }
}

访问:http://localhost:8701/user/manage

7.Consul集群
环境准备
服务器 IPConsul 类型Node 节点
192.168.10.101serverserver-01
192.168.10.102serverserver-02
192.168.10.103serverserver-03
192.168.10.1clientclient-01
安装

安装 unzip 命令,创建 consul 目录,将 consul 解压至指定目录。

yum -y install unzip                                        # 安装 unzip 2  
mkdir -p /usr/local/consul                                  # 创建 consul 目录    unzip consul_1.6.2_linux_amd64.zip -d /usr/local/consul/    # 解压至 consul 目录   
mkdir -p /usr/local/consul/data                             # 创建 consul 数据目录
启动
注册中心服务端

以server 服务模式运行三台注册中心

	# node-01
	./consul agent -server -bind=192.168.10.101 -client=0.0.0.0 -ui -bootstrapexpect=3 -data-dir=/usr/local/consul/data/ -node=server-01
	# node-02
	./consul agent -server -bind=192.168.10.102 -client=0.0.0.0 -ui -bootstrapexpect=3 -data-dir=/usr/local/consul/data/ -node=server-02
	# node-03
	./consul agent -server -bind=192.168.10.103 -client=0.0.0.0 -ui -bootstrapexpect=3 -data-dir=/usr/local/consul/data/ -node=server-03

参数含义如下:

-server :以服务端身份启动(注册中心)

-bind :表示绑定到哪个 ip

-client :指定客户端访问的 ip,0.0.0.0 表示不限客户端 ip

-ui :开启 web 界面访问

-bootstrap-expect=3 :表示 server 集群最低节点数为 3,低于这个值将工作不正常(注:类似

ZooKeeper一样,通常集群数为奇数方便选举,Consul 采用的是 Ra 算法)

-data-dir :表示指定数据的存放目录(该目录必须存在,需提前创建好)

-node :表示节点在 web ui 中显示的名称

注册中心客户端
  consul agent -client=0.0.0.0 -bind=192.168.10.1 -data-dir=D:\Example\consol\data node=client-01
关联集群

在 server-02 和 server-03 和 client-01 节点中输入以下命令建立集群关系。

/consul join 192.168.10.101
集群状态

在任意一台服务器中输入以下命令可查看集群中所有节点信息。

/consul members

访问: http://192.168.10.101:8500/ 或者 http://192.168.10.102:8500/ 或者 http://192.168.10.103:8

Logo

更多推荐