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个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
182 阅读
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
篇文章
累计收到
28
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
3
篇与
的结果
2024-01-01
如何在PHP微服务中实现分布式任务调度和调配
如何在PHP微服务中实现分布式任务调度和调配随着互联网的快速发展,系统的规模和复杂度不断增加,对于任务调度和调配的需求也越来越高。分布式任务调度和调配是一种有效的解决方案,可以将任务根据不同的规则分配到多个节点上进行处理,提高系统的效率和容错性。在PHP微服务中实现分布式任务调度和调配,我们可以借助第三方工具来进行实现,如Redis、RabbitMQ等。下面我将详细介绍如何使用这些工具来实现分布式任务调度和调配,并提供具体的代码示例。使用Redis实现分布式任务调度和调配Redis是一个高性能的键值存储系统,可以实现任务队列的功能。我们可以使用Redis的列表(List)来模拟一个任务队列,将需要执行的任务放入列表中,然后让多个节点通过订阅该列表来获取任务并进行处理。 具体步骤如下:1.1. 创建一个任务队列使用Redis的lpush命令将任务添加到队列中。例如,我们将任务的内容以JSON字符串的形式存储在队列中:$taskData = json_encode(['task_id' => 1, 'task_data' => 'task content']); $redis->lpush('task_queue', $taskData);1.2. 多个节点订阅任务队列多个节点可以通过订阅Redis的消息通道来获取任务。当有新的任务添加到队列中时,Redis会自动推送消息给订阅者。$redis->subscribe(['task_channel'], function ($redis, $channel, $message) { // 获取任务并进行处理 $taskData = json_decode($message, true); $taskId = $taskData['task_id']; $taskContent = $taskData['task_data']; // 执行任务处理逻辑... });使用RabbitMQ实现分布式任务调度和调配RabbitMQ是一个开源的消息代理系统,可以实现高效的任务调度和调配。我们可以使用RabbitMQ的队列(Queue)和发布/订阅模式来实现任务的分发和处理。具体步骤如下:2.1. 创建一个任务队列使用RabbitMQ的发布者向队列中发送任务消息。可以使用AMQP协议库来操作RabbitMQ。$taskData = json_encode(['task_id' => 1, 'task_data' => 'task content']); $connection = new AMQPConnection('localhost', 5672, 'guest', 'guest'); $channel = $connection->channel(); $channel->queue_declare('task_queue', false, true, false, false); $msg = new AMQPMessage($taskData, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]); $channel->basic_publish($msg, '', 'task_queue'); $channel->close(); $connection->close();2.2. 多个节点消费任务队列多个节点可以通过消费RabbitMQ的队列来获取任务。当有新的任务添加到队列中时,RabbitMQ会自动将任务分发给可用的消费者。$connection = new AMQPConnection('localhost', 5672, 'guest', 'guest'); $channel = $connection->channel(); $callback = function ($msg) { // 获取任务并进行处理 $taskData = json_decode($msg->body, true); $taskId = $taskData['task_id']; $taskContent = $taskData['task_data']; // 执行任务处理逻辑... $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']); }; $channel->basic_qos(null, 1, null); $channel->basic_consume('task_queue', '', false, false, false, false, $callback); while (count($channel->callbacks)) { $channel->wait(); } $channel->close(); $connection->close();以上就是在PHP微服务中使用Redis和RabbitMQ实现分布式任务调度和调配的具体示例。通过这些工具,我们可以方便地实现任务的分发和处理,提高系统的灵活性和可扩展性。希望对你有所帮助!
2024年01月01日
11 阅读
0 评论
0 点赞
2023-08-08
用Gearman实现PHP的分布式处理
用Gearman实现PHP的分布式处理本机环境:Debian6 .0+ PHP5.3.3-7+squeeze1先安装任务分发的Job端安装Gearman server and library最新0.20版:wget http://launchpad.net/gearmand/trunk/0.20/+download/gearmand-0.20.tar.gztar zxf gearmand-0.20.tar.gzcd gearmand-0.20./configuresudo makesudo make install中间可能会遇到些问题:在./configure的时候,可能会出现缺少libraries的情况:checking for libevent… noconfigure: error: cannot find the flags to link with Boost program_optionsconfigure: error: libevent is required for gearmand. On Debian this can be found in libevent-dev. On RedHat this can be found in libevent-devel.可能系统缺少libboost、libevent和uuid等等,需要依次安装:sudo apt-get install libboost-program-options-devsudo apt-get install libevent-devsudo apt-get install uuid-dev安装完成后再重新配置安装,安装完成后执行sudo ldconfig因为本试验Client和Worker端都由PHP来实现,所以需要安装php的gearman扩展安装Gearman PHP extension:wget http://pecl.php.net/get/gearman-0.7.0.tgztar zxf gearman-0.7.0.tgzcd gearman-0.7.0phpize./configuresudo makesudo make install中间可能遇到的问题:找不到phpize命令,phpize在php开发包中,所以要先安装php5-devsudo apt-get install php5-dev安装完后,就可以在源码目录中执行phpize生成相关安装配置信息,接着执行后面的./configure等make install后,它告诉你一个目录,生成的gearman.so就在那里。根据需要考到相应PHP的扩展目录里(因为我直接用系统默认安装的php,它自动生成就在扩展中)接下来修改php.ini以使php加载该模块:php –ini看下php.ini在哪里,sudo vim 修改之,在其中加入extension = “gearman.so”然后,开始编写client和worker端client.php<?php$client= new GearmanClient();$client->addServer(“127.0.0.1″, 4730);print $client->do(“title”, “Linvo”);print “\n”;?>worker.php<?php$worker= new GearmanWorker();$worker->addServer(“127.0.0.1″, 4730);$worker->addFunction(“title”, “title_function”);while ($worker->work());function title_function($job){$str = $job->workload();return strlen($str);}?>准备工作已经完毕,试验开始1、启动jobgearmand -d2、启动workerphp -c /etc/php5/apache2/php.ini worker.php3、启动client(新开终端中打开)php -c /etc/php5/apache2/php.ini client.php屏幕显示字符串的长度 “5”这里,有几点需要说明一下:1、这里直接用php cli方式运行,添加-c参数是为了加载php.ini配置文件,以加载gearman扩展2、worker应该做成守护进程(CLI模式),可以开启多个,这样client发起的任务就会分发到各个worker分别来执行(自动负载均衡)这个例子由于太过简单,即使开启多个worker也无法看出效果,不过可以通过终止其中一个,可以看出系统自动切换到其他worker继续正常执行3、同理,client也是可以开启多个的(模型请参考之前的那边日志)4、同时,job也可以开启多个,以避免单点故障
2023年08月08日
8 阅读
0 评论
0 点赞
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 点赞