迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > PHP >

php zookeeper常见问题解决方案

作者:迹忆 最近更新:2022/12/11 浏览次数:

《PHP Zookeeper你需要知道的细节》(以下称为php_zk)一章中我们提出了问题,并且通过分析PHP-ZooKeeper源码找出了问题的原因,但是并没有给出解决方法。本章我们就来看一看解决的办法。

解决的办法分为两种:

一是修改PHP-ZooKeeper源码,重新编译安装
二是修改php代码

下面我们先来看第一种方式。

修改PHP-ZooKeeper源码

在php_zk一章中我们看到,其实在znode节点值为NULL的时候,使用php-zookeeper的get()方法能监听znode节点,但是并不能成功调用回调函数。原因就在于get()这个函数底层实现是当znode值为null的时候调用的函数如下

status = zoo_exists(i_obj->zk, path, 1, &stat);

但是我们可以看一下当znode有值的时候,它会调用到下面的函数

status = zoo_wget(i_obj->zk, path, (fci.size != 0) ? php_zk_watcher_marshal : NULL,
	          cb_data, buffer, &length, &stat);

所以我们分析php_zk_watcher_marshal是解析回调函数的,而在zoo_exists()中第三个参数为1,因此要想解决问题,必须要在zoo_exists()这个函数上找突破。继续进入zoo_exists()函数底层的定义发现其实该函数的实现也很简单

int zoo_exists(zhandle_t *zh, const char *path, int watch, struct Stat *stat)
{              
    return zoo_wexists(zh,path,watch?zh->watcher:0,zh->context,stat);
}

在它的底层又调用了zoo_wexists()函数。所以说我们完全可以在get()函数定义中将zoo_exists()函数改成zoo_wexists()。示例如下

if (max_size <= 0) {
    /*status = zoo_exists(i_obj->zk, path, 1, &stat);*/
    status =zoo_wexists(i_obj->zk,path,(fci.size!=0)?php_zk_watcher_marshal:NULL,cb_data,&stat);
    if (status != ZOK) {
	php_cb_data_destroy(&cb_data);
	php_error_docref(NULL TSRMLS_CC, E_WARNING, "error: %s", zerror(status));
	return;

    }
    length = stat.dataLength;
} else {
    length = max_size;
}

这样一来,回调函数就会被执行了。

保存以后,重新编译安装就可以了

# ./configure --with-libzookeeper-dir=/opt/zk_c/ --with-php-config=/usr/local/php5/bin/php-config
# make
# make test
# make install

因为之前已经在php.ini中添加了zookeeper的配置,所以这里不用在进行任何配置。

完成以后再次按照php_zk文章中进行php代码的运行步骤就会发现能正常的进行新的leader的选举了。

修改php代码

虽然能修改PHP-ZooKeeper的源码来解决问题,但是没有十足的把握还是不要修改源码,因为这可能会影响到其它函数的使用。所以这里我们可以在php代码层来进行修改。

我们在php_zk一章中看到,在进行/cluster子节点的创建中使用的是下面的代码

$this->znode = $this->create(self::CONTAINER . '/w-', null, $this->acl, Zookeeper::EPHEMERAL | Zookeeper::SEQUENCE);

在$this->create()函数中,第三个参数是znode的值,这里我们默认为null。如果我们给他一个不为null的默认值的话,这个问题就迎刃而解了。如下示例

$this->znode = $this->create(self::CONTAINER . '/w-', '1', $this->acl, Zookeeper::EPHEMERAL | Zookeeper::SEQUENCE);

当然我们这里为了测试,只是简单的给了一个1。在实际场景中在创建节点的时候会根据实际应用来给出默认值,这里就暂且使用1来测试。

修改以后再次按照之前的步骤运行——不用在zookeeper客户端单独进行值的设置——就会发现也是能重新选出leader的。

以上两种方式我都是经过代码测试的,实践证明其可行。但是在实际中应该怎样去使用PHP-ZooKeeper都要根据场景去定。我这里只是抛砖引玉,指出在学习中的一些问题,希望能帮到各位。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

修复 Java 未解决的编译错误

发布时间:2023/11/13 浏览次数:160 分类:Java

本文介绍如何修复 Java 中未解决的编译错误。Java 在三个组件上工作:JVM、JRE 和 JDK。JVM(Java 虚拟机)在物理上并不存在,它提供了运行字节码的环境。

将 DLL 反编译为 C++ 源代码

发布时间:2023/08/31 浏览次数:817 分类:C++

本文讨论我们可以用来将 DLL 反编译为 C++ 源代码的工具。反编译器简介 反编译器是一种逆向工程工具。

检查 Linux 中的 C++ 编译器版本

发布时间:2023/08/24 浏览次数:306 分类:C++

本文是关于检查 Linux 操作系统上安装的 C++ 编译器的版本。 此外,在撰写本文时,我们还将探讨 C++ 最新版本 C++ 11 的激活过程。检查 Linux 中的 C++ 编译器版本

在 macOS 中编译 C++ 代码

发布时间:2023/08/18 浏览次数:349 分类:C++

本文包含有关 macOS X 的 C++ 编译器的信息。我们将讨论如何使用命令行界面(即终端)使用 g++ 编译器编译和运行代码。

在 Dev C++ 中编译并运行 C++ 11 代码

发布时间:2023/08/18 浏览次数:164 分类:C++

本文是关于使用 Dev C++ 编译 C++ 11 代码。C++ 11 版本 C++ 11是继C++ 3之后的C++新版本,经国际标准组织(ISO)批准于2011年8月12日发布。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便