无法以编程方式将数据上传到 Zookeeper
Unable to upload data to Zookeeper programmatically
我已经在我的 Ubuntu
机器上安装了 Zookeeper
。我 运行 它处于集群模式,具有三个 z1
、z2
和 z3
实例。当我使用 bin/zkCli.sh -server 127.0.0.1:2181,127.0.0.1:2182,...
连接到它并执行 ls /
时,我看到了一些节点或数据的列表(我不确定术语)。现在我想要的是使用标准 C++
client
以编程方式上传一些数据。为了实现这一点,我有一堆函数,包括 init
,我猜它会启动一个会话,create
函数,它在内部调用 zoo_acreate
和一个空函数(此时为简单起见) 回调函数 create_complete
.
最后提到的两个函数如下所示:
void create(const char * path,
const char * value) {
zoo_acreate(zh,
path,
value,
0,
&ZOO_OPEN_ACL_UNSAFE,
0,
create_completion,
NULL);
}
void create_completion (int rc, const char *value, const void *data) {
// empty at this moment
}
但是,当我尝试使用这些函数将一些数据上传到 zookeeper 时,我没有得到任何结果——实际上,没有错误,但同时没有数据。我使用这些函数的方式是这样的:
int main(){
hostPort = (char *)("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183");
init(hostPort); // as a result of invoking this function
// I see in the console some logs, including this message:
// Initiating client connection, host=127.0.0.1:2181,....
create("/testworker", "");
return 0;
}
我想,这段代码应该在 Zookeeper 中创建一个 /testworker
"folder",然而,它没有 - ls /
命令显示没有变化。我应该指出的一件有趣的事情是,我的程序似乎从未调用 create_completion
回调(我用 cout
检查过)。所以,我的程序可能需要一些特殊的标志和一些特殊的编译字符串。我现在编译的方式是:
$ g++ -o test test.cpp -I /...path_to_include_folder/ -L /..path_to_lib_folder/ -lzookeeper_mt
编辑
我稍微调查了一下这个问题,发现根本没有调用回调函数。例如,启动会话的 init
函数不会调用 main_watcher
回调。这是为什么?
编辑
我又研究了一下。事实证明,zookeeper_init
(在我的 init
函数中调用)returns 0
作为 errno
的值,此外它设置 zh
(这是 static zhandle_t *
类型的动物园管理员处理程序)到某个值,所以 zh
不是 null
等等,根据 documentation、init
函数应该没问题(即使它不会触发回调例程)。所以我在控制台中没有错误消息并且使用标准 zookeeper 方法没有错误标志,但回调和数据上传仍然不起作用,这真的很奇怪。这有什么问题,我该如何调试它?
编辑
这是我的小例子的完整源代码:
#include <iostream>
#include "proto.h"
#include "zookeeper.h"
#include "zookeeper_log.h"
#include "recordio.h"
#include "zookeeper.jute.h"
#include "zookeeper_version.h"
#include "errno.h"
using namespace std;
static char *hostPort;
static zhandle_t * zh;
static int connected = 0;
static int expired = 0;
static int server_id;
static struct String_vector * workers = NULL;
static struct String_vector * tasks = NULL;
void create(const char *, const char *);
void create_completion(int, const char *, const void *);
void main_watcher(zhandle_t *zkh,
int type,
int state,
const char *path,
void* context)
{
// cout << "HELLO FROM WATCHER " << endl; // Not printed when I remove comment. Why???
if(type == ZOO_SESSION_EVENT){
if(state == ZOO_CONNECTED_STATE){
connected = 1;
}
else if(state == ZOO_AUTH_FAILED_STATE){
connected = 0;
}
else if(state == ZOO_EXPIRED_SESSION_STATE){
expired = 1;
connected = 0;
zookeeper_close(zkh);
}
}
}
int init(char* hostPort){
srand(time(NULL));
server_id = rand();
zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
zh = zookeeper_init(hostPort, main_watcher, 15000, 0, 0, 0);
return errno;
}
void create_completion(int rc, const char *value, const void * data){
// empty at this moment for simplicity
}
void create(const char * path, const char * value){
zoo_acreate(zh, path, value, 0, &ZOO_OPEN_ACL_UNSAFE, 0,
create_completion, NULL);
}
int main(){
hostPort = (char *)("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183");
init(hostPort);
create("/testworkers", ""); // Do not see this "folder" /testworkers in Zookeeper. Why???
return 0;
}
编辑
这真让我抓狂。我花了几天时间阅读了一本关于 C++
连接器到 Zookeeper
的书,但没有得到任何结果,我刚刚使用了第一个 Python
连接器,只花了不超过 1.5 分钟就完成了。但这不是我想要的。我想看看如何在 C++
中完成这个微不足道的事情——编译、连接和创建。而已。
编辑
我用 -DTHREADED
选项编译我的程序,但没有用。尽管如此,zoo_acreate
并没有创造任何东西。它不会产生错误消息,不会产生警告,不会 return 错误标志,也不会提供任何结果。真奇怪的图书馆。
您的代码有两个错误。
1.In 这个字符串 static int server_id;
。必须是 static clientid_t server_id;
2.And 你的初始化函数必须是
int init(char* hostPort)
{
//srand(time(NULL));
//server_id = rand();
zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
zh = zookeeper_init(hostPort, main_watcher, 15000, &server_id, 0, 0);
return errno;
}
请注意zookeeper_init
处,函数srand(time(NULL));
和server_id = rand();
必须注释掉。
还有其他事情。查看新版本main。我添加了无限循环。
int main()
{
hostPort = (char *)("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183");
init(hostPort);
create("/testworkers", ""); // Do not see this "folder" /testworkers in Zookeeper. Why???
while(1)
{
sleep(1);
}
return 0;
}
创建 ZNode 时,需要声明基本的 ACL(访问控制列表)- 这里是创建 znode 的基本示例:
static zhandle_t *zh;
static clientid_t myid;
char buffer[512];
struct ACL CREATE_ONLY_ACL[] = {{ZOO_PERM_ALL, ZOO_ANYONE_ID_UNSAFE}};
struct ACL_vector CREATE_ONLY = {1, CREATE_ONLY_ACL};
zh = zookeeper_init("localhost:2181", watcher, 1000, 0, 0, 0);
int rc = zoo_create(zh,"/xyz","value", 5, &CREATE_ONLY, ZOO_EPHEMERAL, buffer, sizeof(buffer)-1);
if (rc) {
fprintf(stdout, "Error %d, %s for %s [%d] - could NOT create /xyz \n", rc, zerror(rc), __FILE__, __LINE__);
}
else
cout << "Created /xyc znode" << endl;
// Watcher function -- basic handling
void watcher(zhandle_t *zzh, int type, int state, const char *path, void* context)
{
fprintf(stdout, "Watcher %s state = %s", type2String(type), state2String(state));
if (path && strlen(path) > 0) {
fprintf(stderr, " for path %s", path);
}
fprintf(stdout, "\n");
if (type == ZOO_SESSION_EVENT) {
if (state == ZOO_CONNECTED_STATE) {
const clientid_t *id = zoo_client_id(zzh);
if (myid.client_id == 0 || myid.client_id != id->client_id) {
myid = *id;
fprintf(stdout, "Got a new session id: 0x%llx\n", _LL_CAST_ myid.client_id);
}
} else if (state == ZOO_AUTH_FAILED_STATE) {
fprintf(stdout, "Authentication failure. Shutting down...\n");
zookeeper_close(zzh);
zh=0;
} else if (state == ZOO_EXPIRED_SESSION_STATE) {
fprintf(stdout, "Session expired. Shutting down...\n");
zookeeper_close(zzh);
zh=0;
}
}
}
这将创建一个 znode - 但是当客户端关闭时它会消失,因为它具有 ZOO_EPHEMERAL 访问权限,如果您希望它在客户端断开连接后仍然存在,则需要更改为不同的ACL
我已经在我的 Ubuntu
机器上安装了 Zookeeper
。我 运行 它处于集群模式,具有三个 z1
、z2
和 z3
实例。当我使用 bin/zkCli.sh -server 127.0.0.1:2181,127.0.0.1:2182,...
连接到它并执行 ls /
时,我看到了一些节点或数据的列表(我不确定术语)。现在我想要的是使用标准 C++
client
以编程方式上传一些数据。为了实现这一点,我有一堆函数,包括 init
,我猜它会启动一个会话,create
函数,它在内部调用 zoo_acreate
和一个空函数(此时为简单起见) 回调函数 create_complete
.
最后提到的两个函数如下所示:
void create(const char * path,
const char * value) {
zoo_acreate(zh,
path,
value,
0,
&ZOO_OPEN_ACL_UNSAFE,
0,
create_completion,
NULL);
}
void create_completion (int rc, const char *value, const void *data) {
// empty at this moment
}
但是,当我尝试使用这些函数将一些数据上传到 zookeeper 时,我没有得到任何结果——实际上,没有错误,但同时没有数据。我使用这些函数的方式是这样的:
int main(){
hostPort = (char *)("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183");
init(hostPort); // as a result of invoking this function
// I see in the console some logs, including this message:
// Initiating client connection, host=127.0.0.1:2181,....
create("/testworker", "");
return 0;
}
我想,这段代码应该在 Zookeeper 中创建一个 /testworker
"folder",然而,它没有 - ls /
命令显示没有变化。我应该指出的一件有趣的事情是,我的程序似乎从未调用 create_completion
回调(我用 cout
检查过)。所以,我的程序可能需要一些特殊的标志和一些特殊的编译字符串。我现在编译的方式是:
$ g++ -o test test.cpp -I /...path_to_include_folder/ -L /..path_to_lib_folder/ -lzookeeper_mt
编辑
我稍微调查了一下这个问题,发现根本没有调用回调函数。例如,启动会话的 init
函数不会调用 main_watcher
回调。这是为什么?
编辑
我又研究了一下。事实证明,zookeeper_init
(在我的 init
函数中调用)returns 0
作为 errno
的值,此外它设置 zh
(这是 static zhandle_t *
类型的动物园管理员处理程序)到某个值,所以 zh
不是 null
等等,根据 documentation、init
函数应该没问题(即使它不会触发回调例程)。所以我在控制台中没有错误消息并且使用标准 zookeeper 方法没有错误标志,但回调和数据上传仍然不起作用,这真的很奇怪。这有什么问题,我该如何调试它?
编辑
这是我的小例子的完整源代码:
#include <iostream>
#include "proto.h"
#include "zookeeper.h"
#include "zookeeper_log.h"
#include "recordio.h"
#include "zookeeper.jute.h"
#include "zookeeper_version.h"
#include "errno.h"
using namespace std;
static char *hostPort;
static zhandle_t * zh;
static int connected = 0;
static int expired = 0;
static int server_id;
static struct String_vector * workers = NULL;
static struct String_vector * tasks = NULL;
void create(const char *, const char *);
void create_completion(int, const char *, const void *);
void main_watcher(zhandle_t *zkh,
int type,
int state,
const char *path,
void* context)
{
// cout << "HELLO FROM WATCHER " << endl; // Not printed when I remove comment. Why???
if(type == ZOO_SESSION_EVENT){
if(state == ZOO_CONNECTED_STATE){
connected = 1;
}
else if(state == ZOO_AUTH_FAILED_STATE){
connected = 0;
}
else if(state == ZOO_EXPIRED_SESSION_STATE){
expired = 1;
connected = 0;
zookeeper_close(zkh);
}
}
}
int init(char* hostPort){
srand(time(NULL));
server_id = rand();
zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
zh = zookeeper_init(hostPort, main_watcher, 15000, 0, 0, 0);
return errno;
}
void create_completion(int rc, const char *value, const void * data){
// empty at this moment for simplicity
}
void create(const char * path, const char * value){
zoo_acreate(zh, path, value, 0, &ZOO_OPEN_ACL_UNSAFE, 0,
create_completion, NULL);
}
int main(){
hostPort = (char *)("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183");
init(hostPort);
create("/testworkers", ""); // Do not see this "folder" /testworkers in Zookeeper. Why???
return 0;
}
编辑
这真让我抓狂。我花了几天时间阅读了一本关于 C++
连接器到 Zookeeper
的书,但没有得到任何结果,我刚刚使用了第一个 Python
连接器,只花了不超过 1.5 分钟就完成了。但这不是我想要的。我想看看如何在 C++
中完成这个微不足道的事情——编译、连接和创建。而已。
编辑
我用 -DTHREADED
选项编译我的程序,但没有用。尽管如此,zoo_acreate
并没有创造任何东西。它不会产生错误消息,不会产生警告,不会 return 错误标志,也不会提供任何结果。真奇怪的图书馆。
您的代码有两个错误。
1.In 这个字符串 static int server_id;
。必须是 static clientid_t server_id;
2.And 你的初始化函数必须是
int init(char* hostPort)
{
//srand(time(NULL));
//server_id = rand();
zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
zh = zookeeper_init(hostPort, main_watcher, 15000, &server_id, 0, 0);
return errno;
}
请注意zookeeper_init
处,函数srand(time(NULL));
和server_id = rand();
必须注释掉。
还有其他事情。查看新版本main。我添加了无限循环。
int main()
{
hostPort = (char *)("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183");
init(hostPort);
create("/testworkers", ""); // Do not see this "folder" /testworkers in Zookeeper. Why???
while(1)
{
sleep(1);
}
return 0;
}
创建 ZNode 时,需要声明基本的 ACL(访问控制列表)- 这里是创建 znode 的基本示例:
static zhandle_t *zh;
static clientid_t myid;
char buffer[512];
struct ACL CREATE_ONLY_ACL[] = {{ZOO_PERM_ALL, ZOO_ANYONE_ID_UNSAFE}};
struct ACL_vector CREATE_ONLY = {1, CREATE_ONLY_ACL};
zh = zookeeper_init("localhost:2181", watcher, 1000, 0, 0, 0);
int rc = zoo_create(zh,"/xyz","value", 5, &CREATE_ONLY, ZOO_EPHEMERAL, buffer, sizeof(buffer)-1);
if (rc) {
fprintf(stdout, "Error %d, %s for %s [%d] - could NOT create /xyz \n", rc, zerror(rc), __FILE__, __LINE__);
}
else
cout << "Created /xyc znode" << endl;
// Watcher function -- basic handling
void watcher(zhandle_t *zzh, int type, int state, const char *path, void* context)
{
fprintf(stdout, "Watcher %s state = %s", type2String(type), state2String(state));
if (path && strlen(path) > 0) {
fprintf(stderr, " for path %s", path);
}
fprintf(stdout, "\n");
if (type == ZOO_SESSION_EVENT) {
if (state == ZOO_CONNECTED_STATE) {
const clientid_t *id = zoo_client_id(zzh);
if (myid.client_id == 0 || myid.client_id != id->client_id) {
myid = *id;
fprintf(stdout, "Got a new session id: 0x%llx\n", _LL_CAST_ myid.client_id);
}
} else if (state == ZOO_AUTH_FAILED_STATE) {
fprintf(stdout, "Authentication failure. Shutting down...\n");
zookeeper_close(zzh);
zh=0;
} else if (state == ZOO_EXPIRED_SESSION_STATE) {
fprintf(stdout, "Session expired. Shutting down...\n");
zookeeper_close(zzh);
zh=0;
}
}
}
这将创建一个 znode - 但是当客户端关闭时它会消失,因为它具有 ZOO_EPHEMERAL 访问权限,如果您希望它在客户端断开连接后仍然存在,则需要更改为不同的ACL