当前位置: 首页 > 后端技术 > PHP

PHP与zookeeper的结合

时间:2023-03-29 22:31:46 PHP

Zookeeper简单介绍ApacheZookeeper是一个开发和维护开源服务器的服务,可以实现高可靠的分布式协调。安装Zookeeper(无需安装)wgethttp://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gztarzxvfzookeeper-3.4.10.tar.gzinstallZookeeperC扩展支持cdzookeeper-3.4.8/src/c./configure--prefix=/usr/makemakeinstallinstallphpzookeeper扩展wgethttps://pecl.php.net/get/zookeeper-0.6.2。tgztarzxvfzookeeper-0.6.2.tgzcdzookeeper-0.6.2phpize./configure--with-libzookeeper-dir=/usr/$make$makeinstallstartzookeeperserver#{zookeeperserver}代表你的zookeeper解压后的目录mkdir-p/project/zookeeper/demo/data#zoo.conf是默认启动加载的配置文件cp/{zookeeperserver}/conf/zoo_sample.cfg/{zookeeperserver}/conf/zoo.cfg/{zookeeperserver}/bin/zkServerstartzookeeperclienttest/{zookeeperserver}/bin/zkCli.sh-server127.0.0.1:2181#[zk:127.0.0.1:2181(CONNECTED)x]客户端连接信息shell[zk:127.0.0.1:2181(CONNECTED)3]ls/[动物园管理员][zk:127.0.0.1:2181(已连接)4]create/testqkl001Created/test[zk:127.0.0.1:2181(CONNECTED)5]create/zgqzgq002Created/zgq[zk:127.0.0.1:2181(CONNECTED)6]ls/[zookeeper,test,zgq][zk:127.0.0.1:2181(CONNECTED)5]delete/zgqCreated/zgq[zk:127.0.0.1:2181(CONNECTED)7]quitPHP下练习zookeeper类信息Zookeeper--Zookeeper类--Zookeeper::addAuth—指定应用程序凭据--Zookeeper::connect—创建句柄以与Zookeeper通信--Zookeeper::__construct—创建句柄以与Zookeeper通信--Zookeeper::create--同步创建节点--Zookeeper::delete—同步删除Zookeeper中的节点—Zookeeper::exists—同步检查Zookeeper节点是否存在—Zookeeper::get—同步获取节点关联的数据—Zookeeper::getAcl—同步获取关联的数据带有节点ACL。--Zookeeper::getChildren--同步列出一个节点的子节点--Zookeeper::getClientId--返回客户端会话ID,仅在连接到当前连接时有效(即最后一个观察者状态为ZooOnCeleDelphi状态)--Zookeeper::getRecvTimeout—返回此会话的超时时间,如果连接当前已连接则有效(仅当最后一个观察者状态为ZooOnCeleTytStand状态时)。服务器重新连接后,此值可能会更改。--Zookeeper::getState—获取Zookeeper连接的状态--Zookeeper::isRecoverable—检查当前Zookeeper连接状态是否可以恢复--Zookeeper::set—设置节点关联的数据--Zookeeper::setAcl—与节点关联的同步设置ACL--Zookeeper::setDebugLevel--设置库的调试级别--Zookeeper::setDeterministicConnOrder--启用/禁用仲裁端点顺序随机化--Zookeeper::setLogStream--设置流用于日志记录的库--Zookeeper::setWatcher--SetwatchfunctionclientoperationzkCli.cmd#output表示连接成功WatchedEventstate:SyncConnectedtype:Nonepath:null[zk:localhost:2181(CONNECTED)0]#下面是运行命令ls/create/ztest1获取节点信息(Zookeeper::get)#get.php$zoo=newZookeeper('192.168.1.45:2181');$r=$zoo->get('/ztest');var_dump($r);获取节点信息(Zookeeper::get)并设置watcher#get.phpclassZookeeperDemo扩展Zookeeper{publicfunctionwatcher($type,$state,$key){var_dump($type);变量转储($状态);变量转储($键);如果($type==3){var_dump($this->get('/zgetw'));//Watcher被消耗所以我们需要设置一个新的$this->get('/zgetw',array($this,'watcher'));}}}$zoo=newZookeeperDemo('192.168.1.45:2181');$zoo->get('/zgetw',[$zoo,'watcher']);while(true){echo'.';sleep(1);}客户端操作set/ztest2set/ztest3set/ztest5获取节点信息(Zookeeper::get)结果phpget.php#output......int(3)int(3)string(6)"/ztest"string(1)"2"..int(3)int(3)string(6)"/ztest"string(1)"3"..int(3)int(3)string(6)"/ztest"string(1)"4".int(3)int(3)string(6)"/ztest"string(1)"5"创建子节点create/ztest/child1c1#output:Created/ztest/child1create/ztest/child2c2#output:Created/ztest/child2ls/ztest#output:[child2,child1]在php子节点下获取#getChild.php$zookeeper=newZookeeper('192.168.1.45:2181');$path='/ztest';$r=$zookeeper->getchildren($path);如果(!empty($r)){foreach($ras$c){var_dump($c);}}#phpgetChild.phpstring(6)"child2"string(6)"child1"创建顺序节点[zk:localhost:2181(CONNECTED)22]create/stest1Created/stest[zk:localhost:2181(CONNECTED)23]铬eate-s/stest/seq1Created/stest/seq0000000000[zk:localhost:2181(CONNECTED)24]create-s/stest/seq1Created/stest/seq0000000001[zk:localhost:2181(CONNECTED)25]create-s/stest/seq1Created/stest/seq0000000002[zk:localhost:2181(CONNECTED)26]create-s/stest/seq1Created/stest/seq0000000003[zk:localhost:2181(CONNECTED)27]create-s/stest/seq1Created/stest/seq0000000004[zk:localhost:2181(CONNECTED)28]create-s/stest/seq1Created/stest/seq0000000005[zk:localhost:2181(CONNECTED)29]create-s/stest/seq1Created/stest/seq0000000006[zk:localhost:2181(CONNECTED)30]create-s/stest/seq1Created/stest/seq0000000007[zk:localhost:2181(CONNECTED)31]create-s/stest/seq2Created/stest/seq0000000008[zk:localhost:2181(连接)32]创建-s/stest/seq2Created/stest/seq0000000009[zk:localhost:2181(CONNECTED)33]create-s/stest/seq2Created/stest/seq0000000010[zk:localhost:2181(CONNECTED))34]创建-s/stest/seq2Created/stest/seq0000000011[zk:localhost:2181(CONNECTED)35]create-s/stest/seq2Created/stest/seq0000000012[zk:localhost:2181(CONNECTED)36]create-s/stest/seq2Created/stest/seq0000000013[zk:localhost:2181(CONNECTED)37]create-s/stest/seq2Created/stest/seq0000000014代码$zookeeper=newZookeeper('192.168.1.45:2181');$aclArray=array(array('perms'=>Zookeeper::PERM_ALL,'scheme'=>'world','id'=>'anyone',));$path='/t3';//ZOO_EPHEMERAL=1//ZOO_SEQUENCE=2//hereflag=NULL,flag=0表示创建永久节点,=1创建临时节点,=2创建临时节点seqsequencenode$realPath=$zookeeper->create($path,null,$aclArray,1);var_dump($realPath);worker是使用顺序临时节点的leader迁移实现#worker.phpZookeeper::PERM_ALL,'scheme'=>'world','id'=>'任何人']];私人$isLeader=false;私人$znode='';私人$prevNode='';公共函数__construct($host='',$watcher_cb=null,$recv_timeout=10000){$this->zk=newZookeeper($host,$watcher_cb,$recv_timeout);}publicfunctionregister(){if(!$this->zk->exists(self::CONTAINER)){$this->zk->create(self::CONTAINER,null,$this->acl);}#创建临时顺序节点$this->znode=$this->zk->create(self::CONTAINER.'/w-',null,$this->acl,Zookeeper::EPHEMERAL|Zookeeper::SEQUENCE);//获取序列节点名,去掉父路径$this->znode=str_replace(self::CONTAINER.'/','',$this->znode);printf("我创建了节点:%s\n",self::CONTAINER.'/'.$this->znode);$this->prevNode=$this->getPrev();我f(is_null($this->prevNode)){$this->setLeader(true);}else{$this->zk->get(self::CONTAINER."/".$this->prevNode,[$this,'watcher']);}}publicfunctiongetPrev(){$workers=$this->zk->getChildren(self::CONTAINER);排序($工人);$size=count($workers);对于($i=0;$i<$size;$i++){if($this->znode==$workers[$i]&&$i>0){return$workers[$i-1];}}返回空值;}publicfunctionwatcher($type,$state,$key){$prevNode=$this->prevNode;printf("watchNode-getPrevious:%s\n",self::CONTAINER."/".$prevNode);if(!is_null($prevNode)){if($type==2){printf($prevNode."haddeleted\n");}if($type==3){printf("我重新监控点:%s\n",self::CONTAINER."/".$prevNode);$this->zk->get(self::CONTAINER."/".$prevNode,[$this,'watcher']);}}}publicfunctionisLeader(){return$this->isLeader;}publicfunctionsetLeader($flag){$this->isLeader=$flag;}publicfunctionrun(){$this->register();while(true){if($this->isLeader()){$this->leaderJob();}else{$this->watcherJob();}睡眠(2);}}publicfunctionleaderJob(){echo"现在我是领导\n";}publicfunctionwatcherJob(){echo"我在监控中:".(self::CONTAINER."/".$this->prevNode)."\n";}}$worker=newWorker('192.168.1.45:2181');$worker->run();Try#Terminal1phpworker.php#Terminal2phpworker.php#Terminal3phpworker.php#这里运行不会受节点变化监控,不会被监控再试#zkClicreate/worker_test/w-/worker_test/0000000020phpworker.php#output我创建了node:/worker_test/w-0000000022我正在监控:/worker_test/w-0000000020我正在监控:/worker_test/w-0000000020watchNode-getPrevious:/worker_test/w-0000000020我正在重新监控节点:/worker_test/w-0000000020我正在监控:/worker_test/w-0000000020我在看:/worker_test/w-0000000020我在看:/worker_test/w-0000000020我在看:/worker_test/w-0000000020我在看:/worker_test/w-0000000020watchNode-getPrevious:/worker_test/w-0000000020我正在重新监控节点:/worker_test/w-00000000202018-08-2802:11:46,684:2486(0x7f28ed0a1700):ZOO_WARN@zookeeper_interest@1570:超过截止时间15ms我正在监控:/worker_test/w-0000000020我正在监控:/worker_test/w-0000000020watchNode-getPrevious:/worker_test/w-0000000020w-0000000020已删除我正在监控:/worker_test/w-0000000020如果我们运行worker.php,我在这里发现了类似的错误直接在worker.php中创建,临时的时序节点不会被watcher访问。在开始监控之前,我们必须先创建相关节点。不知道这是不是PHP版zookeeper的bug。知道的人可以报告Watcher通知状态和事件类型的列表。ZOO_CREATED_EVENT(value=1):节点创建事件,需要监听一个不存在的节点,创建节点时触发,这个监听通过zoo_exists()设置ZOO_DELETED_EVENT(value=2):节点删除事件,这个监听通过zoo_exists()或zoo_get()设置ZOO_CHANGED_EVENT(value=3):节点数据变化事件,本表通过zoo_exists()或zoo_get()设置ZOO_CHILD_EVENT(value=4):子节点列表变化事件,本表通过zoo_get_children()或zoo_get_children2()设置ZOO_SESSION_EVENT(value=-1):session事件,当client与server断开连接或重连时触发ZOO_NOTWATCHING_EVENT(value=-2):watch移除事件,当server由于某种原因不再是clientwatch节点时触发