ZooKeeper单机、集群模式搭建教程
单点配置
ZooKeeper在启动的时候,默认会读取/conf/zoo.cfg配置文件,该文件缺失会报错。因此,我们需要在将容器/conf/挂载出来,在制定的目录下,添加zoo.cfg文件。
-
zoo.cfg
-
logback.xml
配置文件的信息可以从二进制包的conf文件中获取 ZooKeeper的github地址
/conf/zoo.cfg配置文件
#基本时间单位
tickTime=2000#存储数据的目录
dataDir=/data#存储日志的目录
dataLogDir=/datalog #是否以独立模式运行,如果是集群模式,则改为false
standaloneEnabled=true#客户端端口,用户连接zookeeper服务
clientPort=2181
logback.xml日志文件,顺带将输出日志设置了,不设置的话,会采用默认的日志等级
<configuration><property name="zookeeper.console.threshold" value="INFO" /><property name="zookeeper.log.dir" value="." /><property name="zookeeper.log.file" value="zookeeper.log" /><property name="zookeeper.log.threshold" value="WARN" /><property name="zookeeper.log.maxfilesize" value="256MB" /><property name="zookeeper.log.maxbackupindex" value="20" /><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n</pattern></encoder><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>${zookeeper.console.threshold}</level></filter></appender><root level="WARN"><appender-ref ref="CONSOLE" /></root>
</configuration>
docker run -d \--name zookeeper \-v /opt/zookeeperconf/zookeeper1/:/conf/ \zookeeper:3.9.3
之后就可以正常启动了。
我们进入到容器中,验证启动的ZooKeeper是否可以正常使用

# 进入容器内部,使用bash命令行
docker exec -it zookeeper1 /bin/bash# 通过2181端口,连接ZooKeeper服务
bin/zkCli.sh -server 127.0.0.1:2181#创建/zk_test目录,并绑定mydata值
create /zk_test mydata#获取zk_test的绑定值,另外两个ls是列出该目录下,所有的值
get zk_test
集群配置
节点数量说明:
建议配置奇数节点3、5、7、9。原因如下:
ZooKeeper集群模式,只有在超过半数节点可用的情况下,才会对外提供服务;
-
3个节点,允许宕机1个
-
5个节点,允许宕机2个
-
7个节点,允许宕机3个
-
8个节点,也是允许宕机3个,所以配置奇数个,性价比高。
配置文件说明:
logback.xml文件可以共享一个,但是zoo.cgf需要配置不同的文件,因为当server-list列表中的节点是自己的时候,会监听该地址。当节点是别人的时候,去向该地址发起请求,建立连接。所以,zoo.cfg需要是不同的文件。如何判断是否是自己的地址:server.x中的x isEqual ZOO_MY_ID。
搭建步骤:
1.启动多个节点
这里,我们启动三个节点。先将单机模式的配置文件复制三份,并按照下方docker命令将容器依次启动。注意,如果我们进行集群模式的搭建,必须在环境变量中传入ZOO_MY_ID,该值用作节点的编号。【先启动单机,获取每一个节点的IP通信地址,之后再进行配置文件的修改,搭建集群。】
# 节点1,节点与ZOO_MY_ID相对应
docker run -d \--name zookeeper1 \-v /opt/zookeeperconf/zookeeper1/:/conf/ \-e ZOO_MY_ID=1 \zookeeper:3.9.3docker run -d \--name zookeeper2 \-v /opt/zookeeperconf/zookeeper2/:/conf/ \-e ZOO_MY_ID=2 \zookeeper:3.9.3docker run -d \--name zookeeper3 \-v /opt/zookeeperconf/zookeeper3/:/conf/ \-e ZOO_MY_ID=3 \zookeeper:3.9.3

2.查看节点的IP地址
由于Docker中网络模式有多种类型,这里建议,初次搭建集群的同学,直接使用容器本身生成的IP地址。这一步的目的是为了确保zk节点之间能够互相进行通信。熟练了之后,我们可以把他们放到同一个网络下,使用别名进行通信。
docker inspect <ContainerName>

我的三个容器的IPAddress分别为172.17.0.2、172.17.0.3、172.17.0.4。
3.改写配置文件,重启所有节点
接下来进行配置文件的更改,如果启动容器的ZOO_MY_ID等于下方的server.x中的X,将其地址更改为0.0.0.0,表示监听该地址。
# 节点1 ,myid=1
tickTime=2000
dataDir=/data
clientPort=2181
initLimit=5
syncLimit=2
standaloneEnabled=false
server.1=0.0.0.0:2888:3888
server.2=172.17.0.3:2888:3888
server.3=172.17.0.4:2888:3888# 节点2 ,myid=2
tickTime=2000
dataDir=/data
clientPort=2181
initLimit=5
syncLimit=2
standaloneEnabled=false
server.1=172.17.0.2:2888:3888
server.2=0.0.0.0:2888:3888
server.3=172.17.0.4:2888:3888# 节点3 ,myid=3
tickTime=2000
dataDir=/data
clientPort=2181
initLimit=5
syncLimit=2
standaloneEnabled=false
server.1=172.17.0.2:2888:3888
server.2=172.17.0.3:2888:3888
server.3=0.0.0.0:2888:3888
配置文件修改完成之后,我们依次进行集群的重启即可。
docker restart zookeeper1

重启之后,我们查看日志,可以会看到节点1和节点2报java.net.ConnectException: Connection refused的错误信息,这是非常正常的。具体原因看下方节点之间通信错误。
4.验证集群模式是否配置成功
进行其中一个容器,执行bin/zkServer.sh status,会看到以下信息,Mode:表示该节点在集群中的角色。

我们也可以随机进入一个节点,写入一条信息,看看其他节点能不能同步该信息。
搭建集群时常见的错误信息:
1.Cannot assign requested address
错误信息:无法分配、注册,请求的地址。
解决方法:将节点自身的zoo.cfg的IP地址更改为0.0.0.0即可;
2024-11-04 09:41:20,659 [myid:] - ERROR [ListenerHandler-zookeeper01/10.43.187.245:3888:o.a.z.s.q.QuorumCnxManager$Listener$ListenerHandler@1099] - Exception while listening to address zookeeper01/10.43.187.245:3888
java.net.BindException: Cannot assign requested addressat java.base/sun.nio.ch.Net.bind0(Native Method)at java.base/sun.nio.ch.Net.bind(Unknown Source)at java.base/sun.nio.ch.Net.bind(Unknown Source)at java.base/sun.nio.ch.NioSocketImpl.bind(Unknown Source)at java.base/java.net.ServerSocket.bind(Unknown Source)at java.base/java.net.ServerSocket.bind(Unknown Source)at org.apache.zookeeper.server.quorum.QuorumCnxManager$Listener$ListenerHandler.createNewServerSocket(QuorumCnxManager.java:1141)at org.apache.zookeeper.server.quorum.QuorumCnxManager$Listener$ListenerHandler.acceptConnections(QuorumCnxManager.java:1070)at org.apache.zookeeper.server.quorum.QuorumCnxManager$Listener$ListenerHandler.run(QuorumCnxManager.java:1039)at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)at java.base/java.util.concurrent.FutureTask.run(Unknown Source)at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)at java.base/java.lang.Thread.run(Unknown Source)
Connection refused
错误信息:向其他节点发起建立连接的请求,被拒绝了
解决方法:
首先,说明一下,在集群中所有节点没有全部启动的情况下,这种报错是正常的,因为我们的节点没有全部启动,所以自然也就没有办法建立连接了,这种情况下,启动所有的节点,自然就不会报错了。还有一种原因,就是配置文件错误,最大的可能性是IP地址配置错误,导致节点之间一直没有办法进行通信。可以试试在报错的容器内部能不能ping无法建立连接的IP地址
2024-11-04 09:28:03,754 [myid:] - WARN [QuorumConnectionThread-[myid=1]-3:o.a.z.s.q.QuorumCnxManager@401] - Cannot open channel to 2 at election address /10.43.128.163:3888
java.net.ConnectException: Connection refusedat java.base/sun.nio.ch.Net.pollConnect(Native Method)at java.base/sun.nio.ch.Net.pollConnectNow(Unknown Source)at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(Unknown Source)at java.base/sun.nio.ch.NioSocketImpl.connect(Unknown Source)at java.base/java.net.SocksSocketImpl.connect(Unknown Source)at java.base/java.net.Socket.connect(Unknown Source)at org.apache.zookeeper.server.quorum.QuorumCnxManager.initiateConnection(QuorumCnxManager.java:384)at org.apache.zookeeper.server.quorum.QuorumCnxManager$QuorumConnectionReqThread.run(QuorumCnxManager.java:458)at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)at java.base/java.lang.Thread.run(Unknown Source)
主要参考资料:
ZooKeeper官方教程
DockerHub:ZooKeeper
相关文章:
ZooKeeper单机、集群模式搭建教程
单点配置 ZooKeeper在启动的时候,默认会读取/conf/zoo.cfg配置文件,该文件缺失会报错。因此,我们需要在将容器/conf/挂载出来,在制定的目录下,添加zoo.cfg文件。 zoo.cfg logback.xml 配置文件的信息可以从二进制包…...
函数指针示例
目录: 代码: main.c #include <stdio.h> #include <stdlib.h>int Max(int x, int y); int Min(int x, int y);int main(int argc, char**argv) {int x,y;scanf("%d",&x);scanf("%d",&y);int select;printf(&q…...
vue如何实现组件切换
一、使用条件渲染 (v-if) <template><div><button click"currentView ComponentA">Show Component A</button><button click"currentView ComponentB">Show Component B</button><component-a v-if"curren…...
计算机视觉 1-8章 (硕士)
文章目录 零、前言1.先行课程:python、深度学习、数字图像处理2.查文献3.环境安装 第一章:概论1.计算机视觉的概念2.机器学习 第二章:图像处理相关基础1.图像的概念2.图像处理3.滤波器4.卷积神经网络CNN5.图像的多层表示:图像金字…...
整数唯一分解定理
整数唯一分解定理,也称为算术基本定理,是由德国数学家高斯在其著作《算术研究》中首次提出的。本文回顾整数唯一分解定理以及对应的几个重要结论。 一、整数唯一分解定理 整数唯一分解定理,也称为算术基本定理,是数论中的一个重…...
Grass脚本2倍速多账号
前言,小编也是第一次撸空投,我是抱着试一试的态度,梦想总是要有的万一白嫖了呢 Grass 是什么? Grass 扩展程序是一款创新的工具,它可以帮助您释放未使用的网络资源的力量。 通过分享您的剩余带宽,您可以赚…...
15分钟学 Go 第 56 天:架构设计基本原则
第56天:架构设计基本原则 学习目标 理解和掌握基本的架构设计原则,以提升软件系统的可维护性、可扩展性和可重用性。 内容提纲 架构设计原则概述常见架构设计原则 单一职责原则 (SRP)开放/封闭原则 (OCP)里氏替换原则 (LSP)接口分离原则 (ISP)依赖反…...
HTML5 Video(视频)
HTML5 Video(视频) HTML5视频是现代网页设计中不可或缺的一部分,它允许开发者在网页中嵌入视频内容,为用户提供丰富多样的媒体体验。本文将深入探讨HTML5视频的各个方面,包括其基本用法、支持的格式、自定义播放器、浏览器兼容性以及最佳实践。 一、HTML5视频的基本用法 …...
开源模型应用落地-qwen模型小试-Qwen2.5-7B-Instruct-tool usage入门-串行调用多个tools(三)
一、前言 Qwen-Agent 是一个利用开源语言模型Qwen的工具使用、规划和记忆功能的框架。其模块化设计允许开发人员创建具有特定功能的定制代理,为各种应用程序提供了坚实的基础。同时,开发者可以利用 Qwen-Agent 的原子组件构建智能代理,以理解和响应用户查询。 本篇将介绍如何…...
MySQL:表设计
表的设计 从需求中获得类,类对应到数据库中的实体,实体在数据库中表现为一张一张的表,类中的属性就对应着表中的字段(也就是表中的列) 表设计的三大范式: 在数据库设计中,三大范式࿰…...
173. 二叉搜索树迭代器【 力扣(LeetCode) 】
文章目录 零、原题链接一、题目描述二、测试用例三、解题思路四、参考代码 零、原题链接 173. 二叉搜索树迭代器 一、题目描述 实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器: BSTIterato…...
大三学生实习面试经历(1)
最近听了一位学长的建议,不能等一切都准备好再去开始,于是就开始了简历投递,恰好简历过了某小厂的初筛,开启了线上面试,记录了一些问题: (通过面试也确实了解到了自己在某些方面确实做的还不够…...
【论文复现】STM32设计的物联网智能鱼缸
📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀STM32设计的物联网智能鱼缸 【1】项目功能介绍【2】设计需求总结【3】项目硬件模块组成 1.2 设计思路【1】整体设计思路【2】ESP8266工作模式…...
常见长选项和短选项对应表
长选项和短选项的等效形式 在命令行工具中,这种长选项(如--delete)和短选项(如-d)等效的情况很常见。例如--verbose和-v(用于输出详细信息),--quiet和-q(用于安静模式&a…...
Ubuntu24 上安装搜狗输入法
link 首先在终端中依次输入以下代码 sudo apt update sudo apt install fcitx 找到语言支持 在终端中依次输入 sudo cp /usr/share/applications/fcitx.desktop /etc/xdg/autostart/ sudo apt purge ibus 进入网页 搜狗输入法linux-首页 shurufa.sogou.com/linux 找到刚才下…...
【AI图像生成网站Golang】JWT认证与令牌桶算法
AI图像生成网站 目录 一、项目介绍 二、雪花算法 三、JWT认证与令牌桶算法 四、项目架构 五、图床上传与图像生成API搭建 六、项目测试与调试(等待更新) 三、JWT认证与令牌桶算法 在现代后端开发中,用户认证和接口限流是确保系统安全性和性能的两大关键要素…...
关于强化学习的一份介绍
在这篇文章中,我将介绍与强化学习有关的一些东西,具体包括相关概念、k-摇臂机、强化学习的种类等。 一、基本概念 所谓强化学习就是去学习:做什么才能使得数值化的收益信号最大化。学习者不会被告知应该采取什么动作,而是必须通…...
Python3.11.9+selenium,获取图片验证码以及输入验证码数字
Python3.11.9+selenium,获取图片验证码以及输入验证码数字 1、遇到问题:登录或修改密码需要验证码 2、解决办法: 2.1、安装ddddocr pip install ddddocr 2.2、解析验证码函数 import ddddocr def get_capcha_text():#获取验证码图片ele_pic = driver.find_element(By.XPAT…...
Flutter:事件队列,异步操作,链式调用。
Flutter分2种队列 1、事件队列:异步的处理,按顺序执行 import package:flutter/material.dart; main(){testFuture1();testFuture2(); }// 按顺序执行处理A->B->C testFuture1() async {Future((){return 任务A;}).then((value){print(按顺序执行&…...
从零开始学习 sg200x 多核开发之 eth0 自动使能并配置静态IP
前文提到 sophpi 默认没有使能有线网络,需要手工配置: [rootsg200x]~# ifconfig eth0 up [rootsg200x]~# udhcpc -i eth0 [rootsg200x]~# ifconfig eth0 Link encap:Ethernet HWaddr EA:BD:18:08:1E:87 inet addr:192.168.188.142 Bcast:192.1…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
