zookeeper 3.8.4 使用与C API编译
下载
wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4.tar.gz
tar -zxvf apache-zookeeper-3.8.4.tar.gz
cd apache-zookeeper-3.8.4
直接使用
cd conf
cp zoo_sample.cfg zoo.cfg # 将示例配置作为配置
cd …/bin/
./zkServer.sh start # 启动服务
./zkServer.sh status # 查看服务端状态
编译 C API
安装依赖
sudo apt update
sudo apt-get install libssl-dev ant libcppunit-dev maven openjdk-17-jdk
配置jdk环境变量
echo "export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which javac))))" >> ~/.bashrc
source ~/.bashrc
修改 maven镜像
# 修改用户级配置
mkdir -p ~/.m2
cp /usr/share/maven/conf/settings.xml ~/.m2/
vim ~/.m2/settings.xml # 编辑自定义配置
<mirrors>
<mirror>
<id>aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Aliyun Maven Mirror</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
echo $JAVA_HOME # 应输出JDK路径
which javadoc # 确认工具存在
开始编译
# apache-zookeeper-3.8.4/
mvn install -Pfull-build -DskipTests # README_packaging.md
编译后的文件路径
The compiled C client can be found here:
- `zookeeper-client/zookeeper-client-c/target/c/bin` - User executable
- `zookeeper-client/zookeeper-client-c/target/c/lib` - Native libraries
- `zookeeper-client/zookeeper-client-c/target/c/include/zookeeper` - Native library headers
安装到系统路径
# apache-zookeeper-3.8.4/
sudo cp -r zookeeper-client/zookeeper-client-c/target/c/lib/* /usr/local/lib/ #lib
sudo cp -r zookeeper-client/zookeeper-client-c/target/c/include/zookeeper /usr/local/include/ #include
sudo cp zookeeper-client/zookeeper-client-c/target/c/bin/* /usr/local/bin/ #bin
参考
https://www.cnblogs.com/xinyonghu/p/11031729.html
https://blog.csdn.net/qq_18402475/article/details/135623697
error while loading shared libraries: libzookeeper_mt.so.2: cannot open shared object file: No such file or directory
更新动态库缓存
ldconfig
C++ API编程示例
大部分旧版本同步方法被废弃,这里都使用异步方法
#include "zookeeperutil.h"
#include "mprpcapplication.h"
#include <cstring>
#include <iostream>
#include <semaphore.h>
#include <string>
#include <zookeeper/zookeeper.h>
// 生成超时时间 默认10s
void get_timeout_timespec(struct timespec &ts, int timeout_sec = 10)
{
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
ts.tv_sec = now.tv_sec + timeout_sec;
ts.tv_nsec = now.tv_nsec;
}
// 全局watcher观察器
void global_watcher(zhandle_t *zh, int type, int state, const char *path, void *watcherCtx)
{
if (type == ZOO_SESSION_EVENT && state == ZOO_CONNECTED_STATE)
{
std::cout << "success connect zookeeper" << std::endl;
sem_t *sem = (sem_t *)zoo_get_context(zh);
sem_post(sem);
}
}
ZkClient::ZkClient() : m_zhandle(nullptr)
{
// 可按需设置日志等级
// zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
}
ZkClient::~ZkClient()
{
if (m_zhandle != nullptr)
{
zookeeper_close(m_zhandle);
}
}
void ZkClient::Start()
{
std::string host = MpRpcApplication::GetInstance().GetConfig().Load("zookeeperip");
std::string port = MpRpcApplication::GetInstance().GetConfig().Load("zookeeperport");
std::string connstr = host + ":" + port;
m_zhandle = zookeeper_init(connstr.c_str(), global_watcher, 30000, 0, nullptr, 0);
if (m_zhandle == nullptr)
{
std::cerr << "zookeeper_init error" << std::endl;
exit(EXIT_FAILURE);
}
sem_t sem;
sem_init(&sem, 0, 0);
zoo_set_context(m_zhandle, &sem);
struct timespec ts;
get_timeout_timespec(ts);
if (sem_timedwait(&sem, &ts) != 0)
{
std::cerr << "zookeeper connect timeout" << std::endl;
sem_destroy(&sem);
exit(EXIT_FAILURE);
}
sem_destroy(&sem);
std::cout << "zookeeper_init success" << std::endl;
}
void ZkClient::Create(const char *path, const char *data, int datalen, int state)
{
struct CallbackContext
{
int rc; // 异步线程返回值
sem_t sem; // 异步线程同步 信号量
} exists_ctx, create_ctx;
sem_init(&exists_ctx.sem, 0, 0);
exists_ctx.rc = ZSYSTEMERROR;
zoo_aexists(m_zhandle, path, 0,
[](int rc, const struct Stat *, const void *data) {
auto *ctx = (CallbackContext *)data;
ctx->rc = rc;
sem_post(&ctx->sem);
},
&exists_ctx);
struct timespec ts;
get_timeout_timespec(ts);
if (sem_timedwait(&exists_ctx.sem, &ts) != 0)
{
std::cerr << "zoo_aexists timeout for path: " << path << std::endl;
sem_destroy(&exists_ctx.sem);
return;
}
sem_destroy(&exists_ctx.sem);
if (exists_ctx.rc == ZNONODE)
{
// 创建节点
sem_init(&create_ctx.sem, 0, 0);
create_ctx.rc = ZSYSTEMERROR;
zoo_acreate(m_zhandle, path, data, datalen, &ZOO_OPEN_ACL_UNSAFE, state,
[](int rc, const char *value, const void *data) {
auto *ctx = (CallbackContext *)data;
ctx->rc = rc;
sem_post(&ctx->sem);
},
&create_ctx);
get_timeout_timespec(ts);
if (sem_timedwait(&create_ctx.sem, &ts) != 0)
{
std::cerr << "zoo_acreate timeout for path: " << path << std::endl;
sem_destroy(&create_ctx.sem);
return;
}
sem_destroy(&create_ctx.sem);
if (create_ctx.rc == ZOK)
{
std::cout << "znode created: " << path << std::endl;
}
else
{
std::cerr << "znode create failed: " << path << ", error: " << create_ctx.rc << std::endl;
exit(EXIT_FAILURE);
}
}
else if (exists_ctx.rc == ZOK)
{
std::cout << "znode exists: " << path << std::endl;
std::string val = GetData(path);
std::cout << "data: " << val << std::endl;
}
else
{
std::cerr << "zoo_aexists failed: " << path << ", error: " << exists_ctx.rc << std::endl;
}
}
std::string ZkClient::GetData(const char *path)
{
struct GetDataContext
{
char *buffer;
int rc;
sem_t sem;
};
char buf[64] = {0};
GetDataContext ctx{buf, ZSYSTEMERROR};
sem_init(&ctx.sem, 0, 0);
zoo_aget(m_zhandle, path, 0,
[](int rc, const char *value, int value_len,
const struct Stat *, const void *data) {
auto *ctx = (GetDataContext *)data;
ctx->rc = rc;
if (rc == ZOK && value != nullptr)
{
int len = (value_len < 63) ? value_len : 63;
memcpy(ctx->buffer, value, len);
ctx->buffer[len] = '\0';
}
sem_post(&ctx->sem);
},
&ctx);
struct timespec ts;
get_timeout_timespec(ts);
if (sem_timedwait(&ctx.sem, &ts) != 0)
{
std::cerr << "get znode data timeout: " << path << std::endl;
sem_destroy(&ctx.sem);
return "";
}
sem_destroy(&ctx.sem);
if (ctx.rc != ZOK)
{
std::cerr << "get znode data error: " << path << ", rc=" << ctx.rc << std::endl;
return "";
}
return std::string(buf);
}

浙公网安备 33010602011771号