背景:通過判斷某zk節點下是否存在某ip節點,判斷是否服務從zk上摘除。
功能:通過zkserver地址,和要讀取的zk節點路徑,判斷某ip是否存在該節點下。
程序如下:
#include <chrono>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <fstream>
#include <iterator>
#include <thread>
#include <zookeeper/zookeeper.h>
using namespace std;
using std::thread;
using std::atoi;
using std::string;
using std::vector;
using std::pair;
using std::ifstream;
using std::to_string;
using std::exception;
using std::chrono::seconds;
using hrclock = std::chrono::high_resolution_clock;
bool ipExist(string matedata, string path, string ip);
void sessionWatcher(zhandle_t* zk, int type, int state, const char* path, void* ctx);
bool isContainsStr(string str,string contains_str)
{
string::size_type idx = str.find(contains_str);
if (idx!=string::npos) {
return true;
} else {
return false;
}
}
bool ipExist(string matedata, string path, string ip) {
struct String_vector str_vec;
zhandle_t* zk = zookeeper_init(matedata.c_str(), sessionWatcher, 3000, nullptr, nullptr, 0);
if (zk == nullptr) {
std::cout << "zookeeper_init failed" << std::endl;
return false;
}
int ret = zoo_wget_children(zk, path.c_str(), sessionWatcher, nullptr, &str_vec);
if (ret) {
return false;
}
//獲得各份服務ip:port
for (int i = 0; i < str_vec.count; ++i) {
string ipport =str_vec.data[i];//循環獲取該節點下的ip和端口信息
if (isContainsStr(ipport, ip)) {
return true;
}
}
return false;
}
void sessionWatcher(zhandle_t* zk, int type, int state, const char* path, void* ctx) {
if (type == ZOO_SESSION_EVENT) {
if (state == ZOO_CONNECTED_STATE) {
std::cout << "ZOO_CONNECTED_STATE:" << state << std::endl;
} else if (state == ZOO_EXPIRED_SESSION_STATE) {
std::cout << "ZOO_EXPIRED_SESSION_STATE:" << state << std::endl;
thread reconnector([=]() {
std::this_thread::sleep_for(seconds(3));
});
reconnector.detach();
}
}
}
// 介紹:判斷某節點是否存在於zk上的某一路徑下,若不存在返回成功return 0,否則返回失敗return 1
// 參數1:zkserver地址
// 參數2:zk節點路徑
// 參數3:需要檢查的ip 例如"127.0.0.1"
int main(int argc, char **argv) {
try {
string matedata;
string zkregisterpath;
string ip;
if (argc == 4) {
matedata = argv[1];
zkregisterpath = argv[2];
ip = argv[3];
} else {
cout << "error:param should be three!" << endl;
return 1;
}
bool ipexist = ipExist(matedata, zkregisterpath, ip);
if (!ipexist) {//若不存在,說明摘除zk成功
return 0;
} else {
return 1;
}
} catch (exception &e) {
cout << "[ERROR]: " << e.what() << endl;
return 1;
}
}
詳細代碼見附件