Docker-compose安装 可以参考这个

zookeeper官网

zookeeper简要介绍

ZooKeeper是分布式应用程序的高性能协调服务,用于维护配置信息、命名、提供分布式同步和提供组服务。众所周知,协调服务很难做好。它们特别容易出现诸如竞争条件和死锁之类的错误。ZooKeeper 背后的动机是减轻分布式应用程序从头开始实现协调服务的责任。
zookeeper是一个典型的分布式数据一致性的解决方案,分布式应用程序可以基于它实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。

ZooKeeper常用的使用场景就是用于担任服务注册中心。服务提供者将自己的信息注册到ZooKeeper,服务消费者在进行服务调用的时候先到ZooKeeper中查找服务,获取到服务提供者的信息之后,再去调用服务提供者的接口。

搜索zookeeper可用镜像

docker search zookeeper

在这里插入图片描述
安装官方最新版镜像(先不手动拉取也可以,这里安装了,后面docker-compose就不会从远程仓库拉取了,不然他会先从远程仓库拉取镜像)

docker pull zookeeper:latest

在这里插入图片描述
查看这个镜像的详细信息

docker inspect zookeeper

查看镜像元信息可以得知,我们使用的是zookeeper-3.7.0
在这里插入图片描述

创建文件夹

在服务器上部署三个zookeeper节点
服务器创建如下文件夹,便于后面容器zookeeper的指定文件夹(日志文件,配置文件等)的挂载

mkdir -p /home/xt/zookeeper/zookeeper-1/data
mkdir -p /home/xt/zookeeper/zookeeper-1/datalog
mkdir -p /home/xt/zookeeper/zookeeper-1/logs
mkdir -p /home/xt/zookeeper/zookeeper-1/conf

mkdir -p /home/xt/zookeeper/zookeeper-2/data
mkdir -p /home/xt/zookeeper/zookeeper-2/datalog
mkdir -p /home/xt/zookeeper/zookeeper-2/logs
mkdir -p /home/xt/zookeeper/zookeeper-2/conf

mkdir -p /home/xt/zookeeper/zookeeper-3/data
mkdir -p /home/xt/zookeeper/zookeeper-3/datalog
mkdir -p /home/xt/zookeeper/zookeeper-3/logs
mkdir -p /home/xt/zookeeper/zookeeper-3/conf

赋予所有用户对/home/xt/zookeeper文件下的所有文件的读写可执行权限
-R 对目前目录下的所有文件与子目录进行相同的权限变更(即以递归的方式逐个变更)
真正开发的时候不建议赋予所有用户最高权限(自己分好用户组,分别给不同的用户组以不同的权限,避免其他用户不小心修改或删除文件)

chmod -R 777 /home/xt/zookeeper

在每个zookeeper文件夹下面的conf文件夹下创建配置文件zoo.cfg

clientPort=2181
dataDir=/data
dataLogDir=/datalog
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
standaloneEnabled=true
admin.enableServer=true
#和下面的docker-compose 创建的docker container实例对应
server.1=zookeeper-1:2888:3888
server.2=zookeeper-2:2888:3888
server.3=zookeeper-3:2888:3888

clientPort:客户端连接端口,监听客户端连接的端口(默认2181)
dataDir:数据文件目录+数据持久化路径
dataLogDir:日志文件目录

tickTime:通信心跳数,Zookeeper服务器心跳时间,单位毫秒 ,ZooKeeper中最小的时间单位长度 (默认2000ms)

Zookeeper使用的基本时间,服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个tickTime时间就会发送一个心跳,时间单位为毫秒。它用于心跳机制,并且设置最小的session超时时间为两倍心跳时间。(session的最小超时时间是2*tickTime)

initLimit:leader节点和follower节点的初始通信时限,follower节点启动后与leader节点完成数据同步的时间(指定为tickTime的倍数,默认10倍,即20s)。

集群中的followe节点与leader节点之间初始连接时能容忍的最多心跳数(tickTime的数量),用它来限定集群中的Zookeeper服务器连接到Leader的时限。投票选举新leader的初始化时间。
Follower在启动过程中,会从Leader同步所有最新数据,然后确定自己能够对外服务的起始状态。Leader允许follower节点在initLimit时间内完成这个工作。

syncLimit:leader节点和follower节点同步通信时限,进行心跳检测的最大延迟时间(指定为tickTime的倍数,默认5倍,即10s)。

集群中Leader节点与Follower节点之间的最大响应时间单位,假如响应超过syncLimit *
tickTime,Leader认为Follwer死掉,从服务器列表中删除Follwer。在运行过程中,Leader负责与ZK集群中所有机器进行通信,例如通过一些心跳检测机制,来检测机器的存活状态。如果leader节点发出心跳包在syncLimit之后,还没有从follower节点那收到响应,那么就认为这个follower节点已经不在线了。

将log4j.properties日志配置文件也放在每个zookeeper文件夹下面的conf文件夹下
自己下一个指定版本的zookeeper包,自己通过xftp软件移动到服务器上面
这里我把log4j的日志输出文件路径修改了一下,修改到/logs,然后挂载到服务器的logs文件件,我们可以在这里查看log4j的日志文件

zookeeper.log.dir=/logs
# Copyright 2012 The Apache Software Foundation
# 
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Define some default values that can be overridden by system properties
zookeeper.root.logger=INFO, CONSOLE

zookeeper.console.threshold=INFO

zookeeper.log.dir=/logs
zookeeper.log.file=zookeeper.log
zookeeper.log.threshold=INFO
zookeeper.log.maxfilesize=256MB
zookeeper.log.maxbackupindex=20

zookeeper.tracelog.dir=${zookeeper.log.dir}
zookeeper.tracelog.file=zookeeper_trace.log

log4j.rootLogger=${zookeeper.root.logger}

#
# console
# Add "console" to rootlogger above if you want to use this 
#
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=${zookeeper.console.threshold}
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n

#
# Add ROLLINGFILE to rootLogger to get log file output
#
log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold}
log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file}
log4j.appender.ROLLINGFILE.MaxFileSize=${zookeeper.log.maxfilesize}
log4j.appender.ROLLINGFILE.MaxBackupIndex=${zookeeper.log.maxbackupindex}
log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n

#
# Add TRACEFILE to rootLogger to get log file output
#    Log TRACE level and above messages to a log file
#
log4j.appender.TRACEFILE=org.apache.log4j.FileAppender
log4j.appender.TRACEFILE.Threshold=TRACE
log4j.appender.TRACEFILE.File=${zookeeper.tracelog.dir}/${zookeeper.tracelog.file}

log4j.appender.TRACEFILE.layout=org.apache.log4j.PatternLayout
### Notice we are including log4j's NDC here (%x)
log4j.appender.TRACEFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L][%x] - %m%n
#
# zk audit logging
#
zookeeper.auditlog.file=zookeeper_audit.log
zookeeper.auditlog.threshold=INFO
audit.logger=INFO, RFAAUDIT
log4j.logger.org.apache.zookeeper.audit.Log4jAuditLogger=${audit.logger}
log4j.additivity.org.apache.zookeeper.audit.Log4jAuditLogger=false
log4j.appender.RFAAUDIT=org.apache.log4j.RollingFileAppender
log4j.appender.RFAAUDIT.File=${zookeeper.log.dir}/${zookeeper.auditlog.file}
log4j.appender.RFAAUDIT.layout=org.apache.log4j.PatternLayout
log4j.appender.RFAAUDIT.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
log4j.appender.RFAAUDIT.Threshold=${zookeeper.auditlog.threshold}

# Max log file size of 10MB
log4j.appender.RFAAUDIT.MaxFileSize=10MB
log4j.appender.RFAAUDIT.MaxBackupIndex=10

创建docker-compose.yml

zookeeper文件夹下创建docker-compose.yml文件如下

version: '3.9'
# 配置zk集群
# container services下的每一个子配置都对应一个zk节点的docker container

# 给zk集群配置一个网络,网络名为zookeeper-net
networks:
  zookeeper-net:
    name:zookeeper-net
    driver: bridge
    
services:
  zookeeper-1:
    image: zookeeper
    container_name: zookeeper-1
    restart: always
    # 配置docker container和宿主机的端口映射
    ports:
        - 2181:2181
        - 8081:8080
    # 将docker container上的路径挂载到宿主机上 实现宿主机和docker container的数据共享
    volumes:
        - "/home/xt/zookeeper/zookeeper-1/data:/data"
        - "/home/xt/zookeeper/zookeeper-1/datalog:/datalog"
        - "/home/xt/zookeeper/zookeeper-1/logs:/logs"
        - "/home/xt/zookeeper/zookeeper-1/conf:/conf"
    # 配置docker container的环境变量
    environment:
        # 当前zk实例的id
        ZOO_MY_ID: 1
        # 整个zk集群的机器、端口列表
        ZOO_SERVERS: server.1=zookeeper-1:2888:3888 server.2=zookeeper-2:2888:3888 server.3=zookeeper-3:2888:3888
    
    networks:
        - zookeeper-net


  zookeeper-2:
    image: zookeeper
    # 配置docker container和宿主机的端口映射
    container_name: zookeeper-2
    restart: always
    ports:
        - 2182:2181
        - 8082:8080
    # 将docker container上的路径挂载到宿主机上 实现宿主机和docker container的数据共享
    volumes:
        - "/home/xt/zookeeper/zookeeper-2/data:/data"
        - "/home/xt/zookeeper/zookeeper-2/datalog:/datalog"
        - "/home/xt/zookeeper/zookeeper-2/logs:/logs"
        - "/home/xt/zookeeper/zookeeper-2/conf:/conf"
    # 配置docker container的环境变量
    environment:
        # 当前zk实例的id
        ZOO_MY_ID: 2
        # 整个zk集群的机器、端口列表
        ZOO_SERVERS: server.1=zookeeper-1:2888:3888 server.2=zookeeper-2:2888:3888 server.3=zookeeper-3:2888:3888
        
    networks:
        - zookeeper-net
       
    
    
  zookeeper-3:
    image: zookeeper
    container_name: zookeeper-3
    restart: always
    # 配置docker container和宿主机的端口映射
    ports:
        - 2183:2181
        - 8083:8080
    # 将docker container上的路径挂载到宿主机上 实现宿主机和docker container的数据共享
    volumes:
        - "/home/xt/zookeeper/zookeeper-3/data:/data"
        - "/home/xt/zookeeper/zookeeper-3/datalog:/datalog"
        - "/home/xt/zookeeper/zookeeper-3/logs:/logs"
        - "/home/xt/zookeeper/zookeeper-3/conf:/conf"
    # 配置docker container的环境变量
    environment:
        # 当前zk实例的id
        ZOO_MY_ID: 3
        # 整个zk集群的机器、端口列表
        ZOO_SERVERS: server.1=zookeeper-1:2888:3888 server.2=zookeeper-2:2888:3888 server.3=zookeeper-3:2888:3888
        
    networks:
        - zookeeper-net

Zookeeper一共需要用到三个端口:

1、2181:对client端提供服务的端口
2、3888:选举leader使用
3、2888:集群内机器通讯使用(Leader监听此端口)

启动容器

在zookeeper文件夹下,也就是docker-compose.yml文件所在的地方
-d 后台运行

docker-compose up -d

在这里插入图片描述

容器启动成功后,可以通过下面命令查看容器状态

docker ps -a

容器转态为UP,启动成功
在这里插入图片描述

防火墙开放端口,便于外界访问服务器,如果服务器部署了安全组,则安全组也要开放这些端口(如果运行以下命令没用,建议去服务器控制台手动添加端口,我不太明白,好像两种方式添加的端口,效果不一样,服务器控制台手动添加的端口,用firewall-cmd命令查看不到,如果有知道的大佬烦请评论区评论一下)

firewall-cmd --permanent --add-port=2181/tcp
firewall-cmd --permanent --add-port=2182/tcp
firewall-cmd --permanent --add-port=2183/tcp

firewall-cmd --permanent --add-port=8081/tcp
firewall-cmd --permanent --add-port=8082/tcp
firewall-cmd --permanent --add-port=8083/tcp

重启防火墙(修改配置后要重启防火墙)

firewall-cmd --reload

查看开放了那些端口

firewall-cmd --list-ports

端口开放好了之后,由于在配置文件中,将zookeeper-1、zookeeper-2、zookeeper-3的容器内部8080端口分别映射到了宿主机上的8081、8082、8083端口,所以我们可以在自己的电脑上通过浏览器访问这三个zk实例内嵌的web控制台:

http://服务器ip:8081/commands

在这里插入图片描述

在configuration目录下我们可以看到zk实例的基本配置信息,比如server_id、提供客户端服务的端口、数据目录、日志目录等
在这里插入图片描述

在stats目录下可以看到zk实例的运行状态信息,比如节点身份、数据大小、日志大小等.这里三个节点(一个leader,两个follower)

在这里插入图片描述

docker-compose.yml文件部分讲解

在启动完容器之后,我们可以查看部分信息

1、网络配置

顶级的networks标签指定创建了一个标识为zookeeper-net的隔离网络,并且给该网络命名为zookeeper-net。虽然这里将标识和命名都设置为zookeeper-net,但其实他们是不同的配置:

网络标志符是为了配置docker container属于某个网络的标志,而命名是为了开发者能够查看和区分宿主机上的所有网络环境,便于了解宿主机上的系统运行情况
查看宿主机上所有网络

docker network ls

在这里插入图片描述
services标签下的每一个子标签代表一个docker container实例,以zookeeper-1为例。zookeeper-1标签下的networks子标签,表示将zookeeper-1所对应的docker container加入到标识为zookeeper-net的子网中。
所以这里三个节点在一个网络zookeeper-net里面。

通过如下命令查看容器元数据

docker inspect zookeeper-1

在这里插入图片描述

docker inspect zookeeper-2

在这里插入图片描述

docker inspect zookeeper-3

在这里插入图片描述

zookeeper-1、zookeeper-2、zookeeper-3同属于名为zookeeper-net的网络,该网络的网关是192.168.32.1,zookeeper-1、zookeeper-2、zookeeper-3的ip地址分别为
192.168.32.4、192.168.32.3、192.168.32.2

2、环境变量

zookeeper-1、zookeeper-2、zookeeper-3标签下都有一个environment标签,该标签配置的是容器的环境变量。配置在environment标签下的环境变量最终会被添加到docker container的环境变量中,同样可以通过

docker inspect zookeeper-1

在这里插入图片描述
Env标签下除了我们在yml文件中显式配置的环境变量以外,还有一些容器自带的环境变量

ZOO_MY_ID 表示当前zookeeper实例在zookeeper集群中的编号,范围为1-255,所以一个zk集群最多有255个节点
ZOO_SERVERS 表示当前zookeeper实例所在zookeeper集群中的所有节点的编号、端口、主机名(或IP地址)配置

3. 挂载文件

查看容器文件夹的挂载,其他两个zookeeper也一样。(将日志,配置等文件持久化到宿主机)

docker inspect zookeeper-1

我后面将log文件夹修改为了logs(前文配置已修改,主要是log4j的日志输出)
在这里插入图片描述

4. 端口映射

查看容器端口映射方面的信息,其余的两个zookeeper也是一样
访问宿主机的2181就等于访问到容器的2181端口

docker inspect zookeeper-1

HostIp:0.0.0.0 代表宿主机的所有IPV4地址
::,代表宿主机的所有IPV6地址
在这里插入图片描述

References:

  • https://blog.csdn.net/qq_37960603/article/details/121321242
  • https://blog.csdn.net/ypp91zr/article/details/89423878
  • https://blog.csdn.net/weixin_41622183/article/details/90714190
  • https://blog.csdn.net/qq_39340792/article/details/109139406?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.pc_relevant_paycolumn_v2&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.pc_relevant_paycolumn_v2&utm_relevant_index=1
  • https://www.cnblogs.com/kingkoo/p/8732448.html
  • https://blog.csdn.net/baidu_38432732/article/details/116763281
  • https://blog.csdn.net/killer_999/article/details/93762479
  • https://blog.csdn.net/milhua/article/details/78931672
  • https://zhuanlan.zhihu.com/p/121728783
  • https://www.runoob.com/docker/docker-dockerfile.html

(写博客主要是对自己学习的归纳整理,资料大部分来源于书籍、网络资料和自己的实践,整理不易,但是难免有不足之处,如有错误,请大家评论区批评指正。同时感谢广大博主和广大作者辛苦整理出来的资源。)

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐