Deprecated
: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in
/www/wwwroot/testblog.58heshihu.com/var/Widget/Archive.php
on line
1057
首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
184 阅读
2
php接口优化 使用curl_multi_init批量请求
144 阅读
3
《从菜鸟到大师之路 ElasticSearch 篇》
107 阅读
4
2024年备考系统架构设计师
104 阅读
5
PHP 文件I/O
92 阅读
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
登录
Search
标签搜索
php函数
php语法
性能优化
安全
错误和异常处理
问题
vue
Composer
Session
缓存
框架
Swoole
api
并发
异步
正则表达式
php-fpm
mysql 索引
开发规范
协程
dafenqi
累计撰写
786
篇文章
累计收到
33
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
1
篇与
的结果
2023-08-07
使用Apache Zookeeper分布式部署PHP应用程序
使用Apache Zookeeper分布式部署PHP应用程序原文:Distributed application in PHP with Apache Zookeeper地址: http://systemsarchitect.net/distributed-application-in-php-with-apache-zookeeper/ 这篇文章实在不错,实在忍不住翻译下来,希望对大家有用。Apache Zookeeper是我最近遇到的最酷的技术,我是在研究Solr Cloud功能的时候发现的。Solr的分布式计算让我印象深刻。你只要开启一个新的实例就能自动在Solr Cloud中找到。它会将自己分派到某个分片中,并确定出自己是一个Leader(源)还是一个副本。不一会儿,你就可以在你的那些服务器上查询到了。即便某些服务器宕机了也可以继续工作。非常动态、聪明、酷。将运行多个应用程序作为一个逻辑程序并不是什么新玩意。事实上,我在几年前就已写过类似的软件。这种架构比较让人迷惑,使用起来也费劲。为此Apache Zookeeper提供了一套工具用于管理这种软件。为什么叫Zoo?“因为要协调的分布式系统是一个动物园”。在本篇文章中,我将说明如何使用PHP安装和集成Apache ZooKeeper。我们将通过service来协调各个独立的PHP脚本,并让它们同意某个成为Leader(所以称作Leader选举)。当Leader退出(或崩溃)时,worker可检测到并再选出新的leader。ZooKeeper是一个中性化的Service,用于管理配置信息、命名、提供分布式同步,还能组合Service。所有这些种类的Service都会在分布式应用程序中使用到。每次编写这些Service都会涉及大量的修bug和竞争情况。正因为这种编写这些Service有一定难度,所以通常都会忽视它们,这就使得在应用程序有变化时变得难以管理应用程序。即使处理得当,实现这些服务的不同方法也会使得部署应用程序变得难以管理。虽然ZooKeeper是一个Java应用程序,但C也可以使用。这里就有个PHP的扩展,由Andrei Zmievski在2009创建并维护。你可以从PECL中下载,或从GitHub中直接获取PHP-ZooKeeper。要使用该扩展你首先要安装ZooKeeper。可以从官方网站下载。?12345$ tar zxfv zookeeper-3.4.5.tar.gz$ cd zookeeper-3.4.5/src/c$ ./configure --prefix=/usr/$ make$ sudo make install这样就会安装ZooKeeper的库和头文件。现在准备编译PHP扩展。?1234567$ cd$ git clone https://github.com/andreiz/php-zookeeper.git$ cd php-zookeeper$ phpize$ ./configure$ make$ sudo make install将“zookeeper.so”添加到PHP配置中。?1$ vim /etc/php5/cli/conf.d/20-zookeeper.ini因为我不需要运行在web服务环境下,所以这里我只编辑了CLI的配置。将下面的行复制到ini文件中。?1extension=zookeeper.so使用如下命令来确定扩展是否已起作用。?12$ php -m | grep zookeeperzookeeper现在是时候运行ZooKeeper了。目前唯一还没有做的是配置。创建一个用于存放所有service数据的目录。?12345$ mkdir /home/you-account/zoo$ cd$ cd zookeeper-3.4.5/$ cp conf/zoo_sample.cfg conf/zoo.cfg$ vim conf/zoo.cfg找到名为“dataDir”的属性,将其指向“/home/you-account/zoo”目录。?123456$ bin/zkServer.sh start$ bin/zkCli.sh -server 127.0.0.1:2181[zk: 127.0.0.1:2181(CONNECTED) 14] create /test 1Created /test[zk: 127.0.0.1:2181(CONNECTED) 19] ls /[test, zookeeper]此时,你已成功连到了ZooKeeper,并创建了一个名为“/test”的znode(稍后我们会用到)。ZooKeeper以树形结构保存数据。这很类似于文件系统,但“文件夹”(译者注:这里指非最底层的节点)又和文件很像。znode是ZooKeeper保存的实体。Node(节点)的说法很容易被混淆,所以为了避免混淆这里使用了znode。因为我们稍后还会使用,所以这里我们让客户端保持连接状态。开启一个新窗口,并创建一个zookeeperdemo1.php文件。?0102030405060708091011121314151617181920<?phpclass ZookeeperDemo extends Zookeeper { public function watcher( $i, $type, $key ) {echo "Insider Watcher\n"; // Watcher gets consumed so we need to set a new one $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);}现在运行该脚本。?1$ php zookeeperdemo1.php此处应该会每隔2秒产生一个点。现在切换到ZooKeeper客户端,并更新“/test”值。?1[zk: 127.0.0.1:2181(CONNECTED) 20] set /test foo这样就会静默触发PHP脚本中的“Insider Watcher”消息。怎么会这样的?ZooKeeper提供了可以绑定在znode的监视器。如果监视器发现znode发生变化,该service会立即通知所有相关的客户端。这就是PHP脚本如何知道变化的。Zookeeper::get方法的第二个参数是回调函数。当触发事件时,监视器会被消费掉,所以我们需要在回调函数中再次设置监视器。现在你可以准备创建分布式应用程序了。其中的挑战是让这些独立的程序决定哪个(是leader)协调它们的工作,以及哪些(是worker)需要执行。这个处理过程叫做leader选举,在ZooKeeper Recipes and Solutions你能看到相关的实现方法。这里简单来说就是,每个处理(或服务器)紧盯着相邻的那个处理(或服务器)。如果一个已被监视的处理(也即Leader)退出或者崩溃了,监视程序就会查找其相邻(此时最老)的那个处理作为Leader。在真实的应用程序中,leader会给worker分配任务、监控进程和保存结果。这里为了简化,我跳过了这些部分。创建一个新的PHP文件,命名为worker.php。?001002003004005006007008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041042043044045046047048049050051052053054055056057058059060061062063064065066067068069070071072073074075076077078079080081082083084085086087088089090091092093094095096097098099100101102103104105106107108109110111<?phpclass Worker extends Zookeeper { const CONTAINER = '/cluster'; protected $acl = array( array( 'perms' => Zookeeper::PERM_ALL, 'scheme' => 'world', 'id' => 'anyone' ) );private $isLeader = false; private $znode; public function __construct( $host = '', $watcher_cb = null, $recv_timeout = 10000 ) {parent::__construct( $host, $watcher_cb, $recv_timeout );} public function register() {if( ! $this->exists( self::CONTAINER ) ) { $this->create( self::CONTAINER, null, $this->acl ); } $this->znode = $this->create( self::CONTAINER . '/w-', null, $this->acl, Zookeeper::<span class="KSFIND_CLASS" id="0KSFindDIV">EPHEMER</span>AL | Zookeeper::SEQUENCE ); $this->znode = str_replace( self::CONTAINER .'/', '', $this->znode ); printf( "I'm registred as: %s\n", $this->znode ); $watching = $this->watchPrevious(); if( $watching == $this->znode ) { printf( "Nobody here, I'm the leader\n" ); $this->setLeader( true ); } else { printf( "I'm watching %s\n", $watching ); }} public function watchPrevious() {$workers = $this->getChildren( self::CONTAINER ); sort( $workers ); $size = sizeof( $workers ); for( $i = 0 ; $i < $size ; $i++ ) { if( $this->znode == $workers[ $i ] ) { if( $i > 0 ) { $this->get( self::CONTAINER . '/' . $workers[ $i - 1 ], array( $this, 'watchNode' ) ); return $workers[ $i - 1 ]; } return $workers[ $i ]; } } throw new Exception( sprintf( "Something went very wrong! I can't find myself: %s/%s", self::CONTAINER, $this->znode ) );} public function watchNode( $i, $type, $name ) {$watching = $this->watchPrevious(); if( $watching == $this->znode ) { printf( "I'm the new leader!\n" ); $this->setLeader( true ); } else { printf( "Now I'm watching %s\n", $watching ); }} public function isLeader() {return $this->isLeader;} public function setLeader($flag) {$this->isLeader = $flag;} public function run() {$this->register(); while( true ) { if( $this->isLeader() ) { $this->doLeaderJob(); } else { $this->doWorkerJob(); } sleep( 2 ); }} public function doLeaderJob() {echo "Leading\n";} public function doWorkerJob() {echo "Working\n";}}$worker = new Worker( '127.0.0.1:2181' );$worker->run();打开至少3个终端,在每个终端中运行以下脚本?0102030405060708091011121314151617181920term1$ php worker.phpI'm registred as: w-0000000001Nobody here, I'm the leaderLeadingterm2$ php worker.phpI'm registred as: w-0000000002I'm watching w-0000000001Workingterm3$ php worker.phpI'm registred as: w-0000000003I'm watching w-0000000002Working现在模拟Leader崩溃的情形。使用Ctrl+c或其他方法退出第一个脚本。刚开始不会有任何变化,worker可以继续工作。后来,ZooKeeper会发现超时,并选举出新的leader。虽然这些脚本很容易理解,但是还是有必要对已使用的Zookeeper标志作注释。?1234$this->znode = $this->create( self::CONTAINER . '/w-', null, $this->acl, Zookeeper::EPHEMERAL | Zookeeper::SEQUENCE );每个znode都是EPHEMERAL和SEQUENCE的。EPHEMRAL代表当客户端失去连接时移除该znode。这就是为何PHP脚本会知道超时。SEQUENCE代表在每个znode名称后添加顺序标识。我们通过这些唯一标识来标记worker。在PHP部分还有些问题要注意。该扩展目前还是beta版,如果使用不当很容易发生segmentation fault。比如,不能传入普通函数作为回调函数,传入的必须为方法。我希望更多PHP社区的同仁可以看到Apache ZooKeeper的好,同时该扩展也会获得更多的支持。ZooKeeper是一个强大的软件,拥有简洁和简单的API。由于文档和示例都做的很好,任何人都可以很容易的编写分布式软件。让我们开始吧,这会很有趣的。相关连接:Yahoo research on ZooKeeper. 非常好的阅读材料,拥有真实的应用程序示例。如果你只要阅读一份ZooKeeper的资料,那么就是这份了。PHP ZooKeeperPHP ZooKeeper APIPHP ZooKeeper example
2023年08月07日
23 阅读
0 评论
0 点赞