当前位置: 首页 > news >正文

docker 搭建zookper集群,快照虚拟机多机模拟

网上有很多zk集群搭建的,发现踩了很多坑,记录一下自己的搭建:

虚拟机配置

在这里插入图片描述
快照克隆:
在这里插入图片描述
在这里插入图片描述
关闭防火墙。

zk集群正式搭建

查询虚拟机ip地址:

ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v 127.0.0.1

挂载文件地址:

mkdir -p /mydata/zookeeper/data # 数据挂载目录
mkdir -p /mydata/zookeeper/conf # 配置挂载目录
mkdir -p /mydata/zookeeper/logs # 日志挂载目录

关键点,修改配置:

echo 1 > /mydata/zookeeper/conf/myid 

这里是指定zk id,选举需要使用,单机不需要

vim /mydata/zookeeper/conf/zoo.cfg

zoo.cfg创建zk配置,配置如下:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data
dataLogDir=/logs
clientPort=2181
server.1=172.30.123.67:2888:3888
server.2=172.30.123.60:2888:3888
server.3=172.30.115.33:2888:3888

网上很多都是hostname:sudo hostnamectl set-hostname zk2
或者修改/etc/hosts这个文件,通过名称映射ip,这个我也失败了,解析不了。


docker 执行命令:

docker run -d --name zk \--network host \--restart=unless-stopped \-v /mydata/zookeeper/data:/data \-v /mydata/zookeeper/logs:/logs \-v /mydata/zookeeper/conf:/conf \-e ZOO_MY_ID=$(cat /mydata/zookeeper/data/myid) \zookeeper:3.5.7

这个有点坑,我试了其他博主的博客,大多都是直接-p去映射,但是我这边尝试一直链接不是,采用 --network host。
–network host 让容器直接使用宿主机网络,端口 2181/2888/3888 不用再 -p 映射。

集群验证:

docker exec zk zkServer.sh status

显示:

ZooKeeper JMX enabled by default
Using config: /conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower

follower就是选举角色,到这里就成功了,其他的虚拟机上还有leader。

简单使用java连接集群

pom.xml:
添加依赖

<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.8.0</version></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>5.9.0</version></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>5.9.0</version></dependency>

生产客户端bean:

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ZookeeperConfig {@Value("${curator.connectString}")private String connectString;@Value("${curator.sessionTimeoutMs}")private int sessionTimeoutMs;@Value("${curator.connectionTimeoutMs}")private int connectionTimeoutMs;@Value("${curator.retryCount}")private int retryCount;@Value("${curator.elapsedTimeMs}")private int elapsedTimeMs;@Bean(initMethod = "start", destroyMethod = "close")public CuratorFramework curatorFramework() {RetryPolicy retryPolicy = new ExponentialBackoffRetry(elapsedTimeMs, retryCount);return CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).build();}
}

注册服务bean:

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.nodes.PersistentNode;
import org.apache.zookeeper.CreateMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.concurrent.TimeUnit;@Component
public class ZookeeperServiceRegistry {@Autowiredprivate CuratorFramework curatorFramework;/*** 注册服务节点* @param serviceName 服务名* @param serviceAddress 实例地址,如 127.0.0.1:8080* @return PersistentNode 句柄,方便后续关闭*/public PersistentNode registerService(String serviceName, String serviceAddress) throws Exception {// 1. 先保证父节点存在String parent = "/services/" + serviceName;Stat stat = curatorFramework.checkExists().forPath(parent);if (stat == null) {curatorFramework.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath(parent);}// 2. 子节点路径,使用 EPHEMERAL 即可,不需要 SEQUENTIALString childPath = parent + "/" + serviceAddress;// 3. 创建临时节点PersistentNode node = new PersistentNode(curatorFramework,CreateMode.EPHEMERAL,   // 会话断后自动删除false,                  // false 表示不监听子节点childPath,serviceAddress.getBytes());node.start();if (!node.waitForInitialCreate(10, TimeUnit.SECONDS)) {throw new IllegalStateException("Failed to create node at " + childPath);}return node;}/*** 注销服务节点(若仍持有 PersistentNode,先关闭再删除)*/public void unregisterService(String serviceName, String serviceAddress) throws Exception {String path = "/services/" + serviceName + "/" + serviceAddress;// 如果之前保存了 PersistentNode,先关闭// node.close();curatorFramework.delete().forPath(path);}
}

使用spring CommandLineRunner 钩子,主动注册

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;@Component
public class ServiceRegistrationRunner implements CommandLineRunner {@Autowiredprivate ZookeeperServiceRegistry serviceRegistry;@Overridepublic void run(String... args) throws Exception {serviceRegistry.registerService("my-service", "127.0.0.1:8080");System.out.println("Service registered successfully.");}
}
http://www.dtcms.com/a/356480.html

相关文章:

  • 2025数学建模国赛AI提示词模板
  • 如何解决网关断网后时间不再统计的问题?无RTC子设备如何打通主网关的时间同步功能?
  • 法律审查prompt收集
  • 高并发内存池(19)-用基数树优化
  • IDA-pro-mcp 的核心功能 常用的prompt
  • Mybatis的常用标签
  • word去空格去空行_word辅助工具 word批量处理
  • 【C++】类与对象(上)
  • Matlab实现基于CPO-QRCNN-BiGRU-Attention注意力多变量时间序列区间预测
  • FPGA实现1553B BC控制器IP方案
  • 【AOSP】Android Dump 开发与调试指南
  • Replay – AI音乐伴奏分离工具,自动分析音频内容、提取主唱、人声和伴奏等音轨
  • 栈和队列OJ习题
  • 【物联网】关于 GATT (Generic Attribute Profile)基本概念与三种操作(Read / Write / Notify)的理解
  • 如何在mysql中执行创建数据库的脚本文件?
  • Spring Boot 使用 RestTemplate 调用 HTTPS 接口时报错:PKIX path building failed 解决方案
  • Linux下的网络编程SQLITE3详解
  • 神经语言学视角:脑科学与NLP深层分析技术的交叉融合
  • Java的CAS机制:无锁并发控制及其高频面试题
  • OpenCSG月度更新2025.8
  • 1 分钟 Maya 动画渲染要多久?5 天还是 5 小时
  • 基于Java、GeoTools与PostGIS的GeoJSON动态属性注入实战指南
  • 在 Go 项目的 DDD 分层架构中,Echo Web 框架及其 middleware 应该归属到哪一层?
  • mysql安全运维之安全模型与原则-构建坚不可摧的数据库防护体系
  • 自然语言提取PDF表格数据
  • 电影交流|基于SprinBoot+vue的电影交流平台小程序系统(源码+数据库+文档)
  • 在基于 Go 的 DDD 分层架构中,包含多个server的项目目录结构应如何组织?
  • LoraConfig target modules加入embed_tokens(64)
  • 设计模式-行为型模式-命令模式
  • Spring 微服务架构下的单元测试优化实践:从本地连接到真实开发数据库的集成测试