ZooKeeper是一個分布式的,開放源碼的分布式應用程序協調服務,是Google的Chubby一個開源的實現,是Hadoop和Hbase的重要組件。它是一個為分布式應用提供一致性服務的軟件,提供的功能包括:配置維護、域名服務、分布式同步、組服務等。
ZooKeeper的目標就是封裝好復雜易出錯的關鍵服務,將簡單易用的接口和性能高效、功能穩定的系統提供給用戶。
要在php中使用zookeeper,先要安裝php zookeeper擴展,要安裝php zookeeper擴展,得先安裝zookeeper
1、安裝zookeeper
在這里面下載最新版的穩定版
http://mirror.bit.edu.cn/apache/zookeeper/stable/
cd /download
wget http://mirror.bit.edu.cn/apache/zookeeper/stable/zookeeper-3.4.12.tar.gz //這個是已經安裝好的工具,下面我們還需要自己編譯安裝一下,因為后面安裝php的擴展時用得到
tar -zxvf zookeeper-3.4.12.tar.gz
cd zookeeper-3.4.12/src/c/
./configure --prefix=/usr/local/zookeeper //指定一下安裝目錄
make && make install
就這樣安裝完了
2、安裝php zookeeper的擴展 在 http://pecl.php.net/package/zookeeper中找
cd /download
wget http://pecl.php.net/get/zookeeper-0.6.2.tgz
tar -zxvf zookeeper-0.6.2.tgz
cd zookeeper-0.6.2
./configure --with-libzookeeper-dir=/usr/local/zookeeper //要指定依賴
make && make install
配置php.ini
extension="/usr/local/Cellar/php/7.2.6/pecl/20170718/zookeeper.so"
重啟php-fpm即可
3、啟動zookeeper前要安裝jdk 已經安裝的可以忽略
在http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html里面下載
然后傻瓜式安裝,這里不說了
4、啟動zookeeper
cd /download/zookeeper-3.4.12/bin
./zkServer.sh start
./zkCli.sh -server 127.0.0.1:2181
cli方式開啟
注意:
如果報錯:
cd ../conf
cp zoo_sample.cfg zoo.cfg
復制一下文件
5、php代碼測試
測試代碼1、
-
-
/**
-
*
-
*/
-
class zookeeperDemo
-
{
-
private $zookeeper;
-
function __construct($address)
-
{
-
$this->zookeeper = new Zookeeper($address);
-
}
-
/*
-
* get
-
*/
-
public function get($path)
-
{
-
if (!$this->zookeeper->exists($path)) {
-
return null;
-
}
-
return $this->zookeeper->get($path);
-
}
-
-
public function getChildren($path) {
-
if (strlen($path) > 1 && preg_match('@/$@', $path)) {
-
// remove trailing /
-
$path = substr($path, 0, -1);
-
}
-
return $this->zookeeper->getChildren($path);
-
}
-
/*
-
* set 值
-
*
-
*
-
*/
-
public function set($path, $value)
-
{
-
if (!$this->zookeeper->exists($path)) {
-
//創建節點
-
$this->makePath($path);
-
} else {
-
$this->zookeeper->set($path,$value);
-
}
-
-
}
-
/*
-
* 創建路徑
-
*/
-
private function makePath($path, $value='')
-
{
-
$parts = explode( '/', $path);
-
$parts = array_filter($parts); //過濾空值
-
$subPath = '';
-
while (count($parts) > 1) {
-
$subPath .= '/' . array_shift($parts);//數組第一個元素彈出數組
-
if (!$this->zookeeper->exists($subpath)) {
-
$this->makeNode($subPath, $value);
-
}
-
}
-
}
-
/*
-
* 創建節點
-
*
-
*/
-
private function makeNode($path, $value, array $params = array())
-
{
-
if (empty($params)) {
-
$params = [
-
[
-
'perms' => Zookeeper::PERM_ALL,
-
'scheme' => 'world',
-
'id' => 'anyone'
-
]
-
];
-
}
-
return $this->zookeeper->create($path, $value, $params);
-
}
-
/*
-
* 刪除
-
**/
-
public function deleteNode($path)
-
{
-
if (!$this->zookeeper->exists($path)) {
-
return null;
-
} else {
-
return $this->zookeeper->delete($path);
-
}
-
}
-
-
}
-
$zk = new zookeeperDemo('localhost:2181');
-
//var_dump($zk->get('/zookeeper'));
-
var_dump($zk->getChildren( '/foo'));
-
//var_dump($zk->deleteNode("/foo"));
-
-
測試代碼2、
-
-
/**
-
* PHP Zookeeper
-
*
-
* PHP Version 5.3
-
*
-
* The PHP License, version 3.01
-
*
-
* @category Libraries
-
* @package PHP-Zookeeper
-
* @author Lorenzo Alberton <l.alberton@quipo.it>
-
* @copyright 2012 PHP Group
-
* @license http://www.php.net/license The PHP License, version 3.01
-
* @link https://github.com/andreiz/php-zookeeper
-
*/
-
/**
-
* Example interaction with the PHP Zookeeper extension
-
*
-
* @category Libraries
-
* @package PHP-Zookeeper
-
* @author Lorenzo Alberton <l.alberton@quipo.it>
-
* @copyright 2012 PHP Group
-
* @license http://www.php.net/license The PHP License, version 3.01
-
* @link https://github.com/andreiz/php-zookeeper
-
*/
-
class Zookeeper_Example
-
{
-
/**
-
* @var Zookeeper
-
*/
-
private $zookeeper;
-
/**
-
* @var Callback container
-
*/
-
private $callback = array();
-
/**
-
* Constructor
-
*
-
* @param string $address CSV list of host:port values (e.g. "host1:2181,host2:2181")
-
*/
-
public function __construct($address) {
-
$this->zookeeper = new Zookeeper($address);
-
}
-
/**
-
* Set a node to a value. If the node doesn't exist yet, it is created.
-
* Existing values of the node are overwritten
-
*
-
* @param string $path The path to the node
-
* @param mixed $value The new value for the node
-
*
-
* @return mixed previous value if set, or null
-
*/
-
public function set($path, $value) {
-
if (!$this->zookeeper->exists($path)) {
-
$this->makePath($path);
-
$this->makeNode($path, $value);
-
} else {
-
$this->zookeeper->set($path, $value);
-
}
-
}
-
/**
-
* Equivalent of "mkdir -p" on ZooKeeper
-
*
-
* @param string $path The path to the node
-
* @param string $value The value to assign to each new node along the path
-
*
-
* @return bool
-
*/
-
public function makePath($path, $value = '') {
-
$parts = explode( '/', $path);
-
$parts = array_filter($parts);
-
$subpath = '';
-
while (count($parts) > 1) {
-
$subpath .= '/' . array_shift($parts);
-
if (!$this->zookeeper->exists($subpath)) {
-
$this->makeNode($subpath, $value);
-
}
-
}
-
}
-
/**
-
* Create a node on ZooKeeper at the given path
-
*
-
* @param string $path The path to the node
-
* @param string $value The value to assign to the new node
-
* @param array $params Optional parameters for the Zookeeper node.
-
* By default, a public node is created
-
*
-
* @return string the path to the newly created node or null on failure
-
*/
-
public function makeNode($path, $value, array $params = array()) {
-
if (empty($params)) {
-
$params = array(
-
array(
-
'perms' => Zookeeper::PERM_ALL,
-
'scheme' => 'world',
-
'id' => 'anyone',
-
)
-
);
-
}
-
return $this->zookeeper->create($path, $value, $params);
-
}
-
/**
-
* Get the value for the node
-
*
-
* @param string $path the path to the node
-
*
-
* @return string|null
-
*/
-
public function get($path) {
-
if (!$this->zookeeper->exists($path)) {
-
return null;
-
}
-
return $this->zookeeper->get($path);
-
}
-
/**
-
* List the children of the given path, i.e. the name of the directories
-
* within the current node, if any
-
*
-
* @param string $path the path to the node
-
*
-
* @return array the subpaths within the given node
-
*/
-
public function getChildren($path) {
-
if (strlen($path) > 1 && preg_match('@/$@', $path)) {
-
// remove trailing /
-
$path = substr($path, 0, -1);
-
}
-
return $this->zookeeper->getChildren($path);
-
}
-
-
/**
-
* Delete the node if it does not have any children
-
*
-
* @param string $path the path to the node
-
*
-
* @return true if node is deleted else null
-
*/
-
-
public function deleteNode($path)
-
{
-
if(!$this->zookeeper->exists($path))
-
{
-
return null;
-
}
-
else
-
{
-
return $this->zookeeper->delete($path);
-
}
-
}
-
-
/**
-
* Wath a given path
-
* @param string $path the path to node
-
* @param callable $callback callback function
-
* @return string|null
-
*/
-
public function watch($path, $callback)
-
{
-
if (!is_callable($callback)) {
-
return null;
-
}
-
-
if ($this->zookeeper->exists($path)) {
-
if (!isset($this->callback[$path])) {
-
$this->callback[$path] = array();
-
}
-
if (!in_array($callback, $this->callback[$path])) {
-
$this->callback[$path][] = $callback;
-
return $this->zookeeper->get($path, array($this, 'watchCallback'));
-
}
-
}
-
}
-
-
/**
-
* Wath event callback warper
-
* @param int $event_type
-
* @param int $stat
-
* @param string $path
-
* @return the return of the callback or null
-
*/
-
public function watchCallback($event_type, $stat, $path)
-
{
-
if (!isset($this->callback[$path])) {
-
return null;
-
}
-
-
foreach ($this->callback[$path] as $callback) {
-
$this->zookeeper->get($path, array($this, 'watchCallback'));
-
return call_user_func($callback);
-
}
-
}
-
-
/**
-
* Delete watch callback on a node, delete all callback when $callback is null
-
* @param string $path
-
* @param callable $callback
-
* @return boolean|NULL
-
*/
-
public function cancelWatch($path, $callback = null)
-
{
-
if (isset($this->callback[$path])) {
-
if (empty($callback)) {
-
unset($this->callback[$path]);
-
$this->zookeeper->get($path); //reset the callback
-
return true;
-
} else {
-
$key = array_search($callback, $this->callback[$path]);
-
if ($key !== false) {
-
unset($this->callback[$path][$key]);
-
return true;
-
} else {
-
return null;
-
}
-
}
-
} else {
-
return null;
-
}
-
}
-
}
-
$zk = new Zookeeper_Example('localhost:2181');
-
// var_dump($zk->get('/'));
-
// var_dump($zk->getChildren('/'));
-
// var_dump($zk->set('/test', 'abc'));
-
// var_dump($zk->get('/test'));
-
// var_dump($zk->getChildren('/'));
-
// var_dump($zk->set('/foo/001', 'bar1'));
-
// var_dump($zk->set('/foo/002', 'bar2'));
-
// var_dump($zk->get('/'));
-
// var_dump($zk->getChildren('/'));
-
// var_dump($zk->getChildren('/foo'));
-
-
//watch example 一旦/test節點的值被改變,就會調用一次callback
-
function callback() {
-
echo "in watch callback\n";
-
}
-
//$zk->set('/test', 1);
-
$ret = $zk->watch( '/test', 'callback');
-
//$zk->set('/test', 2);//在終端執行
-
while (true) {
-
sleep( 1);
-
}
-
-
/*
-
class ZookeeperDemo extends Zookeeper {
-
-
public function watcher( $i, $type, $key ) {
-
echo "Insider Watcher\n";
-
-
// Watcher gets consumed so we need to set a new one
-
-
//ZooKeeper提供了可以綁定在znode的監視器。如果監視器發現znode發生變化,該service會立即通知所有相關的客戶端。這就是PH//P腳本如何知道變化的。Zookeeper::get方法的第二個參數是回調函數。當觸發事件時,監視器會被消費掉,所以我們需要在回調函
-
//數中再次設置監視器。
-
-
$this->get( '/test', array($this, 'watcher' ) );
-
-
}
-
-
}
-
-
$zoo = new ZookeeperDemo('127.0.0.1:2181');
-
$zoo->get( '/test', array($zoo, 'watcher' ) );
-
-
while( true ) {
-
echo '.';
-
sleep(2);
-
}
-
*/
-
/*
-
-
// $zc = new Zookeeper();
-
-
// $zc->connect('127.0.0.1:2181');
-
-
// var_dump($zc->get('/zookeeper'));
-
-
// exit;
-
*/
-
-
代碼參考鏈接:
https://github.com/php-zookeeper/php-zookeeper/blob/master/examples/Zookeeper_Example.php