zookeeper c api主备切换例子
步骤:
1.准备3台主机并同步好时间。
2.在主机1启动zookeeper服务,创建节点/services
3.在主机2运行应用程序,连接主机1的zookeeper
4.主机2往zookeeper的/services节点注册临时节点,节点名=IP:端口 节点数据=注册时间us
5.主机2监听/services节点
6.分别在主机1,主机3启动运行应用程序;分别向zookeeper注册临时节点。并监听/services节点。
7.以先启动的应用程序为主机,及节点数据小的为主机。
8.三台主机运行起来后,只有一台为主机,其余为备机。
zkCli.h
#ifndef _ZKCLIENT_H_
#define _ZKCLIENT_H_#ifdef _WIN32#include "zk\include\zookeeper.h"#include "zk\include\zookeeper.jute.h"#include "zk\include\zookeeper_log.h"#include "zk\include\zookeeper_version.h"
#else#include <zookeeper/zookeeper.h>#include <sys/types.h>#include <ifaddrs.h>#include <arpa/inet.h>#include <sys/socket.h>#include <netdb.h>#include <stdlib.h>#include <unistd.h>#include <net/if.h>#include <errno.h>#include <string.h>#include <pthread.h>
#endif#define INFO(fmt, args...) printf("[%s:%d %s][INFO]");printf(fmt, ##args);typedef void(*FUN)(const char*, const char*);class ZkCli
{private:zhandle_t *m_ZkHandle;pthread_mutex_t m_mutex;pthread_cond_t m_cond;bool m_Connected;char m_servAddr[64];char m_zkAddr[64];char m_path[64];FUN m_func;
public:ZkCli();~ZkCli();bool zkInit(const char* zkaddr, const char* path);int Create(const char* path);int Set(const char* path, const char* data, int size);void Register(const char* listenIp, const unsigned short listenPort, FUN func);void getLocalIp(char *localIp, int len);private:int64_t getTimeStampUs();void setConnected(bool stat);void ServiceWatch(const char* path);private:/*typedef void (*watcher_fn)(zhandle_t *zh, int type, int state, const char *path, void *watcherCtx);*/static void init_watcher(zhandle_t *zh, int type, int stat, const char* path, void* watcherCtx);static void require_wachter(zhandle_t *zh, int type, int stat, const char* path, void* watcherCtx);
};#endif
zkCli.cpp
#include "zkCli.h"
#include <sys/time.h>
#include <unordered_map>ZkCli::ZkCli()
: m_ZkHandle(NULL),
m_Connected(false)
{pthread_mutex_init(&m_mutex, NULL);pthread_cond_init(&m_cond, NULL);
}ZkCli::~ZkCli()
{pthread_mutex_destroy(&m_mutex);pthread_cond_destroy(&m_cond);zookeeper_close(m_ZkHandle);
}int64_t ZkCli::getTimeStampUs()
{struct timeval stamp;gettimeofday(&stamp, NULL);return (int64_t)(stamp.tv_sec * 1000000 + stamp.tv_usec);
}void ZkCli::setConnected(bool stat)
{if (stat){pthread_cond_signal(&m_cond);}m_Connected = stat;
}void ZkCli::init_watcher(zhandle_t *zh, int type, int stat, const char* path, void* watcherCtx)
{ZkCli* pCli = (ZkCli*)watcherCtx;if (type == ZOO_SESSION_EVENT){if (stat == ZOO_CONNECTING_STATE){pCli->setConnected(false);}else if (stat == ZOO_CONNECTED_STATE){pCli->setConnected(true);}else if (stat == ZOO_NOTCONNECTED_STATE){pCli->setConnected(false);}}
}void ZkCli::require_wachter(zhandle_t* zh, int type, int stat, const char* path, void* watherCtx)
{printf("require_wachter() : type=%d, stat=%d, path=%s\n", type, stat, path);ZkCli* pZkCli = (ZkCli*)watherCtx;pZkCli->ServiceWatch(path);
}void ZkCli::getLocalIp(char* localIp, int len)
{struct ifaddrs *ifaddr;if (getifaddrs(&ifaddr) == -1){printf("getifaddr failed, errno=%d, errmsg=%s\n", errno, strerror(errno));exit(EXIT_FAILURE);}char host[NI_MAXHOST];for (struct ifaddrs *ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {if (ifa->ifa_addr == NULL)continue;int family = ifa->ifa_addr->sa_family;if (!ifa->ifa_flags & IFF_BROADCAST){continue;}if (family == AF_INET || family == AF_INET6){int s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);if (s != 0){printf("getnameinfo() failed: %s\n", gai_strerror(s));break;}if (strcmp(host, "127.0.0.1")){strncpy(localIp, host, len);break;}}}freeifaddrs(ifaddr);
}bool ZkCli::zkInit(const char* zkAddr, const char* path)
{zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);m_ZkHandle = zookeeper_init(zkAddr, init_watcher, 3000, NULL, this, 0);if (!m_ZkHandle){INFO("zookeeper_init failed, zkAddr:%s, errno=%d, errmsg=%s\n", zkAddr, errno, strerror(errno));return false;}strncpy(m_zkAddr, zkAddr, sizeof(m_zkAddr));struct timeval now;gettimeofday(&now, NULL);pthread_mutex_lock(&m_mutex);struct timespec waitTime;waitTime.tv_sec = now.tv_sec + 5;waitTime.tv_nsec = now.tv_usec * 1000;pthread_cond_timedwait(&m_cond, &m_mutex, &waitTime);pthread_mutex_unlock(&m_mutex);strncpy(m_path, path, sizeof(m_path));int ret = Create(path);if (ret != ZOK && ret != ZNODEEXISTS){printf("create root path failed, path=%s\n", path);return false;}ServiceWatch(path);return true;
}int ZkCli::Create(const char* path)
{char path_buffer[256] = { 0 };int ret = zoo_create(m_ZkHandle, path, "", -1, &ZOO_OPEN_ACL_UNSAFE, 0, path_buffer, sizeof(path_buffer)-1);if (ret == ZOK){printf("create node %s succeed!\n", path);}else{printf("create node %s, ret=%d\n", path, ret);}return ret;
}int ZkCli::Set(const char* path, const char* data, int size)
{char path_buffer[256] = { 0 };int ret = zoo_create(m_ZkHandle, path, data, size, &ZOO_OPEN_ACL_UNSAFE, ZOO_EPHEMERAL, path_buffer, sizeof(path_buffer)-1);if (ret == ZOK){printf("set [%s]=[%s] succeed!\n", path_buffer, data);}else{printf("set [%s]=[%s] failed, ret=%d\n", path, data, ret);}return ret;
}void ZkCli::ServiceWatch(const char* path)
{/*ZOOAPI int zoo_wget_children(zhandle_t *zh, const char *path,watcher_fn watcher,void* watcherCtx,struct String_vector *strings);*/String_vector strvect;int rc = zoo_wget_children(m_ZkHandle, path, require_wachter, this, &strvect);if (rc != ZOK){printf("zoo_wget_children faield, path:%s, rc=%d\n", path, rc);return;}std::string master_server;uint64_t min_starttimeus = 0;for (int i = 0; i < strvect.count; i++){printf("str[%d]:%s\n", i, strvect.data[i]);char nodepath[64] = { 0 };snprintf(nodepath, sizeof(nodepath)-1, "%s/%s", path, strvect.data[i]);char buffer[256] = { 0 };int buffer_len = sizeof(buffer);if (ZOK == zoo_get(m_ZkHandle, nodepath, 0, buffer, &buffer_len, NULL)){uint64_t startTimeus = atoll(buffer);if (min_starttimeus == 0){min_starttimeus = startTimeus;master_server = strvect.data[i];}else if (min_starttimeus > startTimeus){min_starttimeus = startTimeus;master_server = strvect.data[i];}printf("%s=%ld\n", nodepath, startTimeus);}}printf("master server=%s, timeus=%ld\n", master_server.c_str(), min_starttimeus);if (strcmp(m_servAddr, master_server.c_str()) == 0){printf("should switch to master!\n");if (m_func){m_func("","");}}else{printf("should switch to slave!\n");}
}void ZkCli::Register(const char* listenIp, const unsigned short listenPort, FUN func)
{snprintf(m_servAddr, sizeof(m_servAddr)-1, "%s:%d", listenIp, listenPort);m_func = func;int64_t TimeStampUs = getTimeStampUs();char TimeStampStr[32] = { 0 };snprintf(TimeStampStr, sizeof(TimeStampStr)-1, "%ld", TimeStampUs);char ServicePath[128] = { 0 };snprintf(ServicePath, sizeof(ServicePath)-1, "%s/%s", m_path, m_servAddr);Set(ServicePath, TimeStampStr, strlen(TimeStampStr));
}
Makefile
CC=g++ -g
SRC=$(wildcard *.cpp)
OBJ=${SRC:%.cpp=%.o}FLAG=-DTHREADED
LIB=-lpthread -lzookeeper_mtTARGET=zk_clientall:${TARGET}${TARGET}:${OBJ}${CC} -o ${TARGET} ${OBJ} ${LIB}%.o:%.cpp${CC} ${FLAG} -c $? -o $@
运行结果:
62:
[root@localhost zk_client]# ./zk_client
create node /services, ret=-110
master server=, timeus=0
should switch to slave!
zookeeper connected!
require_wachter() : type=4, stat=3, path=/services
set [/services/192.168.1.62:9044]=[1632473624547276] succeed!
str[0]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.62:9044, timeus=1632473624547276
should switch to master!
enter switch func
require_wachter() : type=4, stat=3, path=/services
str[0]:192.168.1.86:9044
/services/192.168.1.86:9044=1632473592590648
str[1]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.86:9044, timeus=1632473592590648
should switch to slave!
require_wachter() : type=4, stat=3, path=/services
str[0]:192.168.1.86:9044
/services/192.168.1.86:9044=1632473592590648
str[1]:192.168.1.85:9044
/services/192.168.1.85:9044=1632473596504658
str[2]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.86:9044, timeus=1632473592590648
should switch to slave!
86:
[root@localhost zk_client]# ./zk_client
create node /services, ret=-110
str[0]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.62:9044, timeus=1632473624547276
should switch to slave!
zookeeper connected!
require_wachter() : type=4, stat=3, path=/services
set [/services/192.168.1.86:9044]=[1632473592590648] succeed!
str[0]:192.168.1.86:9044
/services/192.168.1.86:9044=1632473592590648
str[1]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.86:9044, timeus=1632473592590648
should switch to master!
enter switch func
require_wachter() : type=4, stat=3, path=/services
str[0]:192.168.1.86:9044
/services/192.168.1.86:9044=1632473592590648
str[1]:192.168.1.85:9044
/services/192.168.1.85:9044=1632473596504658
str[2]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.86:9044, timeus=1632473592590648
should switch to master!
enter switch func
85:
[root@localhost zk_client]# ./zk_client
create node /services, ret=-110
str[0]:192.168.1.86:9044
/services/192.168.1.86:9044=1632473592590648
str[1]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.86:9044, timeus=1632473592590648
should switch to slave!
zookeeper connected!
require_wachter() : type=4, stat=3, path=/services
set [/services/192.168.1.85:9044]=[1632473596504658] succeed!
str[0]:192.168.1.86:9044
/services/192.168.1.86:9044=1632473592590648
str[1]:192.168.1.85:9044
/services/192.168.1.85:9044=1632473596504658
str[2]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473624547276
master server=192.168.1.86:9044, timeus=1632473592590648
should switch to slave!
86为主机。
关闭62后:
85切换为主机
require_wachter() : type=4, stat=3, path=/services
str[0]:192.168.1.85:9044
/services/192.168.1.85:9044=1632473768385849
str[1]:192.168.1.62:9044
/services/192.168.1.62:9044=1632473810040201
master server=192.168.1.85:9044, timeus=1632473768385849
should switch to master!
enter switch func
zookeeper c api主备切换例子相关推荐
- Namenode主备切换或报 IPC Server handler 23 on 8020
转自:http://blog.csdn.net/u014033218/article/details/75570313 可能是以下原因,未测试: NameNode 高可用整体架构概述 在 Hadoop ...
- MySQL 集群(三):MySQL + Mycat 实现读写分离,主备切换集群
MySQL 集群(三):MySQL + Mycat 实现读写分离,主从切换集群 下载 Mycat Mycat 主要文件 端口 Mycat 命令 配置文件 server.xml schema.xml 配 ...
- vrrp路由器三种状态_VRRP路由器切换方法、路由器、VRRP主备切换系统及存储介质与流程...
本发明涉及虚拟路由冗余协议(VRRP)技术领域,尤其涉及一种VRRP路由器切换方法.路由器.VRRP主备切换系统及存储介质. 背景技术: 虚拟路由冗余协议(Virtual Router Redunda ...
- nginx+tomcat实现主备切换
一.准备工作 1.nginx安装 1.1.准备工作 选首先安装这几个软件:GCC,PCRE(Perl Compatible Regular Expression),zlib,OpenSSL. Ngin ...
- 在三台Redis节点上部署哨兵集群以及主备切换、故障恢复的容灾演练中哨兵各自的日志信息、状态查看分析
1. 创建哨兵的配置文件 先在 /etc 目录创建一个sentinel目录作为哨兵的配置信息存放目录,并将Redis安装目录的sentinel.conf文件(我这边路径是 /usr/local/red ...
- oracle adg切换原理,oracle11g ADG主备切换
oracle11g ADG主备切换 1.主库 SQL> select name,open_mode,switchover_status from v$database; NAME OPEN_MO ...
- Spark之Master主备切换机制原理
Spark之Master主备切换机制原理
- 《MySQL——基于位点orGTID的主备切换协议》
一主多从的设置,用于读写分离,主库负责所有的写入和一部分读,其他读请求则由从库分担. 一主多从架构下,主库故障后的主备切换问题.相比于一主一备,多了从库指向新主库的过程. 基于位点的主备切换同步 把节 ...
- 《MySQL——主备切换流程与主备延迟》
目录 主备切换 主备延迟的原因 可靠性优先策略的主备切换流程 可用性优先策略的主备切换流程 主备切换 主备切换分为主动运维与被动操作. 软件升级.主库所在机器按计划下线为主动运维. 主库所在机器掉电为 ...
最新文章
- jQuery.click()与onClick
- Java中int转Double再转换成百分数并应用在求同比昨日增长率
- HttpClient 学习整理
- flex java类转成_Flex 与 java 通讯 【转】
- Java 8系列之重新认识HashMap(转载自美团点评技术团队)
- 微信小程序------MD5加密(支持中文和不支持中文)和网络请求(get和post)
- layui轮播图切换会有跳动_Layui中轮播图切换函数说明
- JEECG Excel 介绍篇
- linux apache支持ipv6,如何在Nginx和Apache中启用IPv6?
- 江湖传说——阿里巴巴土话102句完整版
- c语言小游戏跳一跳代码及注释,c语言小游戏程序之弹跳小球的实现代码
- 听说你也想修改IP归属地?
- 用生成对抗网络给雪人上色,探索人工智能时代的美学
- OKR-Periods of Words
- 招银网络 Java后端面经
- 防火墙服务器搭建与应用(1.0)
- docker占用磁盘空间太大的解决办法
- 机器学习笔记(三)—— 二向箔(从PCA到SVD)
- 初学者第一个JavaWeb项目实战【附源码】
- pandas数据上采样
热门文章
- 基于Adobe LCDS产品的数据访问解决方案Part3
- 用python写 祝你生日快乐英文_祝你生日快乐的英文怎么写
- stata实操|从国泰安到stata数据集以及初步的数据处理
- win7系统计算机在哪里打开,win7摄像头怎么打开 win7系统摄像头在哪
- vim 光标快速移动技巧总结(vim高级操作的基础)from csdner 亓磊
- 壁布接缝压条_教你2招搞定墙布毛边翘边
- 一款很实用的欠压过压保护电路
- 生物信息学在线服务器,生物信息学杂志
- x1计算机价格,除了不靠谱的售价,X1 Carbon 是一台完美的 ThinkPad
- 网页文字复制的几种方法