Zookeeper C++编程实战之主备切换
默认zookeeper日志输出到stderr,
可以调用zoo_set_log_stream(FILE*)设置输出到文件中
还可以调用zoo_set_debug_level(ZooLogLevel)控制日志级别!!!
类CZookeeperHelper提供基于zookeeper的主备切换接口和读取数据等接口:
https://github.com/eyjian/libmooon/blob/master/include/mooon/net/zookeeper_helper.h
使用示例:
class CMyApplication: public mooon::net::CZookeeperHelper
{
public:
CMyApplication(const char* data);
void stop() { _stop = true; }
void run();
void wait(); private:
void work(); private:
virtual void on_zookeeper_session_connected(const char* path);
virtual void on_zookeeper_session_connecting(const char* path);
virtual void on_zookeeper_session_expired(const char *path);
virtual void on_zookeeper_session_event(int state, const char *path);
virtual void on_zookeeper_event(int type, int state, const char *path); private:
volatile bool _stop;
std::string _master_path; 用来竞争master的zookeeper节点路径
std::string _master_data; 成功竞争为master时,写入_master_path的数据,主备应当提供不同的数据,以方便判断自己是否处于主状态
}; int main(int argc, char* argv[])
{
try
{
mooon::sys::g_logger = mooon::sys::create_safe_logger();
const std::string zk_nodes = "127.0.0.1:2181";
const int session_timeout_seconds = 1; CMyApplication myapp(argv[1]);
myapp.create_session(zk_nodes, session_timeout_seconds);
myapp.run();
myapp.wait(); return 0;
}
catch (mooon::sys::CSyscallException& ex)
{
fprintf(stderr, "%s\n", ex.str().c_str());
exit(1);
}
catch (mooon::utils::CException& ex)
{
fprintf(stderr, "%s\n", ex.str().c_str());
exit(1);
}
} CMyApplication::CMyApplication(const char* data)
: _stop(false)
{
_master_path = "/tmp/a";
if (data != NULL)
_master_data = data;
} void CMyApplication::run()
{
启动时竞争master,
在成为master之前不能进入工作状态
while (!_stop)
{
int zk_errcode;
std::string zk_errmsg; if (race_master(_master_path, _master_data, &zk_errcode, &zk_errmsg))
{
成为master后,
要让原来的master有足够时间退出master状态
MYLOG_INFO("Race master at %s with %s successfully, sleep for 10 seconds to let the old master quit\n", _master_path.c_str(), _master_data.c_str());
mooon::sys::CUtils::millisleep(10000);
MYLOG_INFO("Start working now\n"); work();
if (!_stop)
{
退出work(),表示需要重新竞争master
MYLOG_INFO("Turn to slave from master at %s with %s successfully, stop working now\n", _master_path.c_str(), _master_data.c_str());
}
}
else
{
如果node_exists_exception()返回true,表示已有master,
即_master_path已存在,返回false为其它错误,应将错误信息记录到日志
if (node_exists_exception(zk_errcode))
{
MYLOG_INFO("A master exists\n");
}
else
{
MYLOG_ERROR("Race master at %s with %s failed: (state:%d)(errcode:%d)%s\n", _master_path.c_str(), _master_data.c_str(), get_state(), zk_errcode, zk_errmsg.c_str());
if (invalid_handle_exception(zk_errcode))
{
MYLOG_INFO("To recreate session\n");
recreate_session();
}
} 休息2秒后再尝试,不要过频重试,一般情况下1~10秒都是可接受的
mooon::sys::CUtils::millisleep(2000);
}
} MYLOG_INFO("Exit now\n");
} void CMyApplication::wait()
{
} void CMyApplication::work()
{
要及时检查is_connected(),以防止master失效后同时存在两个master
while (!_stop && !is_session_expired())
{
mooon::sys::CUtils::millisleep(2000);
MYLOG_INFO("Working with state:\033[1;33m%d\033[m ...\n", get_state());
}
} void CMyApplication::on_zookeeper_session_connected(const char* path)
{
MYLOG_INFO("[\033[1;33mon_zookeeper_session_connected\033[m] path: %s\n", path); const std::string zk_parent_path = "";
const std::string zk_node_name = "test";
const std::string zk_node_data = "123"; try
{
create_node(zk_parent_path, zk_node_name, zk_node_data, ZOO_EPHEMERAL);
MYLOG_INFO("Create %s/%s ok\n", zk_parent_path.c_str(), zk_node_name.c_str());
}
catch (mooon::utils::CException& ex)
{
MYLOG_ERROR("Create %s/%s failed: %s\n", zk_parent_path.c_str(), zk_node_name.c_str(), ex.str().c_str());
}
} void CMyApplication::on_zookeeper_session_connecting(const char* path)
{
MYLOG_INFO("[\033[1;33mon_zookeeper_session_connecting\033[m] path: %s\n", path);
} void CMyApplication::on_zookeeper_session_expired(const char *path)
{
MYLOG_INFO("[\033[1;33mon_zookeeper_session_expired\033[m] path: %s\n", path);
//exit(1); 最安全的做法,在这里直接退出,通过重新启动方式再次竞争master
} void CMyApplication::on_zookeeper_session_event(int state, const char *path)
{
MYLOG_INFO("[\033[1;33mon_zookeeper_session_event\033[m][state:%d] path: %s\n", state, path);
} void CMyApplication::on_zookeeper_event(int type, int state, const char *path)
{
MYLOG_INFO("[\033[1;33mon_zookeeper_event\033[m][type:%d][state:%d] path: %s\n", type, state, path); if (type == 3)
{
const int data_size = mooon::SIZE_4K;
const bool keep_watch = true;
std::string zk_data;
const int n = get_zk_data(path, &zk_data, data_size, keep_watch);
printf("(%d/%zd)%s\n", n, zk_data.size(), zk_data.c_str());
}
}
Zookeeper C++编程实战之主备切换的更多相关文章
- 基于zookeeper的主备切换方法
继承CZookeeperHelper即可快速实现主备切换: https://github.com/eyjian/libmooon/blob/master/include/mooon/net/zooke ...
- Zookeeper C++编程实战之配置更新
CZookeeperHelper:https://github.com/eyjian/libmooon/blob/master/include/mooon/net/zookeeper_helper.h ...
- Spark系列(五)Master主备切换机制
Spark Master主备切换主要有两种机制,之中是基于文件系统,一种是基于Zookeeper.基于文件系统的主备切换机制需要在Active Master挂掉后手动切换到Standby Master ...
- 大话Spark(7)-源码之Master主备切换
Master作为Spark Standalone模式中的核心,如果Master出现异常,则整个集群的运行情况和资源都无法进行管理,整个集群将处于无法工作的状态. Spark在设计的时候考虑到了这种情况 ...
- Nginx+Keepalived主备切换(包含nginx服务停止)
原文地址:http://blog.sina.com.cn/s/blog_79ac6aa80101bmed.html Nginx+Keepalived主备切换(包含nginx服务停止) 环境: VM中4 ...
- 在Windows Azure上配置VM主备切换(1)——Linux篇
对任何一个上线系统来说,高可用设计是不可或缺的一个环节,这样才可以确保应用可以持续.稳定的运行,而不是频繁的掉线.停机.高可用设计的核心思路很简单,就是消除一切单点故障,将单点链路或者节点升级为多点. ...
- (摘)DataGuard物理standby管理 - 主备切换
DataGuard物理standby管理 - 主备切换 Dataguard的切换分为两种,switchover和failover. switchover一般用于数据库或硬件升级,这时只需要较短时间中断 ...
- 测试redis+keepalived实现简单的主备切换【转载】
转自: 测试redis+keepalived实现简单的主备切换 - Try My Best 尽力而为 - ITeye技术网站http://raising.iteye.com/blog/2311757 ...
- Redis安装,主从,主备切换
网络环境: 主:10.187.120.5 从:10.187.69.58 从:10.187.69.59 一.安装 mv redis-2.8.19.tar.gz /export/servers/ cd / ...
随机推荐
- vue内引入jsPlumb流程控制器(一)
1. npm i jsplumb --save 注:jsplumb要全小写 2. 在main.js内 加: import jsPlumb from 'jsplumb' Vue.prototype.$j ...
- ABP框架使用Mysql数据库
参考文档:https://github.com/ABPFrameWorkGroup/AbpDocument2Chinese/blob/master/Markdown/Abp/9.4ABP%E5%9F% ...
- Java图形界面——Border
Swing编程边框(Border)的用法总结 Java进行客户端编程,使用了大量的Swing控件,由于系统默认的边框无法满足项目的要求,不得不自己更改控件的边框样式,网上找了不少资料,本文对Swing ...
- java8 数据结构的改变(二) 对ConcurrentHashMap影响
https://www.cnblogs.com/study-everyday/p/6430462.html http://www.importnew.com/22007.html
- Python.tornado.2.tornado.options
记录Tornado-4.0.2源码的阅读,学习,分析 options.py 1. imports 部分 1.1 __future__ from __future__ import absolute_i ...
- iOS.Info.plist
1. Custom message when asking for Address Book Permissions http://kevinyavno.com/blog/?p=176
- js对象(BOM部分/DOM部分)
JS总体包括ECMAScript,DOM,BOM三个部分,但是能够和浏览器进行交互的只有DOM和BOM,那么到底什么是DOM和BOM呢 概念 BOM(Browser Object Model)是指浏览 ...
- LIbreOJ #6011. 「网络流 24 题」运输问题 最小费用最大流
#6011. 「网络流 24 题」运输问题 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
- UI设计师经常去的五个网站
1.站酷 站酷(ZCOOL),中国人气设计师互动平台.深耕设计领域十年,站酷聚集了470万优秀设计师.摄影师.插画师.艺术家.创意人,设计创意群体中具有较高的影响力与号召力. 2.花瓣 花瓣网, ...
- [转]11种常见sqlmap使用方法详解
sqlmap也是渗透中常用的一个注入工具,其实在注入工具方面,一个sqlmap就足够用了,只要你用的熟,秒杀各种工具,只是一个便捷性问题,sql注入另一方面就是手工党了,这个就另当别论了.今天把我一直 ...