有时,我们的服务需要在用户交互后执行一些巨大的任务。 例如,我们需要发送一封信,生成一个报告文件或调用外部API。 由于第三方,此类任务可能会变慢,并且会消耗服务器的资源。
在这种情况下,就像《小王子 》( The Little Prince)一书中的那样,一个应用程序可能变成一条吞噬大象的蛇。 您从用户那里获取一些数据并让他等待,因为蛇需要一些时间来消化大象(或者您的应用程序需要执行的其他操作):
为了更快地处理此功能,您需要使应用程序的各个部分异步 。 您可以通过将任务委派给功能更强大的服务器或在后台进程中运行它来实现。
Gearman是可以用来执行此操作的合适工具。
我们会做什么?
在本教程中,我们将创建一个简单的应用程序,它将客户端的任务委托给Gearman worker。 我们的应用程序将通过三个过程来计算斐波那契数列。 要运行工作进程,我们将安装和配置Supervisor。
请注意,本教程中的示例需要PHP7才能运行。
那么,反正Gearman是什么?
首先,让我们从首页中了解Gearman是什么:
Gearman提供了一个通用的应用程序框架,可以将工作分配到更适合执行该工作的其他机器或进程。 它允许您并行执行工作,进行负载平衡处理以及在语言之间调用函数。 它可用于各种应用程序,从高可用性网站到数据库复制事件的传输。 换句话说,它是分布式处理如何通信的神经系统。
换句话说,Gearman是一个排队系统,由于支持多种语言,因此可以轻松地在许多服务器上进行扩展并且灵活使用。
安装Gearman
如果您正在运行Debian / Ubuntu,请运行以下命令以使用必要的工具和PHP扩展名安装Gearman:
sudo apt-get install gearman php-gearman gearman-tools
之后,运行Gearman服务器并检查状态:
sudo gearmand -d
gearadmin --status
但是,在status命令之后,您将看不到任何有用的信息,因为我们尚未启动任何工作程序。 请记住这一点,直到我们需要它为止。
创建一个客户
现在我们准备启动一个名为client.php
的脚本。 该脚本将创建Gearman客户端,并将信息发送到同一台计算机上的服务器:
<?php
// create gearman client
$client = new GearmanClient();
$client->addServer('127.0.0.1');
// config
$numbers = [
1, 2
];
// do a task with gearman worker
$res = $client->doNormal('get_sequence', json_encode($numbers));
您可能已经注意到我们以JSON格式发送了数字。 Gearman客户和工作人员以字符串格式互相交谈,因此序列化数组的方法之一是使用json_encode()
函数或类似方法。
收到工作人员的回答后,我们将使用json_decode()
将其json_decode()
序列化并输出为CSV行:
<?php
// decode answer
$lines = json_decode($res, true);
if (empty($lines)) {
die('empty answer');
}
// output as csv
foreach ($lines as $numbers) {
$line = implode(', ', $numbers);
echo($line . PHP_EOL);
}
我们刚刚完成了客户端脚本,因此让我们从终端运行它:
php /vagrant/tuts-gearman-supervisor/code/client.php
但是它将卡住而没有任何输出。 为什么? 它正在等待工人连接。
创建一个工人
现在是时候创建一个工作人员来执行客户订购的工作了。 我们将需要一个带有fibonacci()
函数的文件,并在当前服务器上创建一个新的Gearman worker:
<?php
require_once __DIR__ . '/lib.php';
$worker = new GearmanWorker();
$worker->addServer('127.0.0.1');
之后,我们将添加一个新功能,该功能与在客户端代码中调用的功能相同:
<?php
$worker->addFunction('get_sequence', function ($job) {
// decode input
$content = $job->workload();
$data = json_decode($content, true);
// calculate sequence and return result
$rows = fibonacci($data);
return json_encode($rows);
});
而且,当然,不要忘记将答案包装为JSON格式。 最后要做的是循环工作脚本以多次使用它,而无需重新启动:
<?php
for ($i = 0; $i < 100; ++$i) {
$worker->work();
}
我们可以在后台运行worker脚本:
php /vagrant/tuts-gearman-supervisor/code/worker.php &
此刻,您可能已经观察到客户端脚本已结束其工作并编写了以下内容:
vagrant@localserver:~$ /vagrant/tuts-gearman-supervisor/code/client.php
1, 2, 3
2, 3, 5
3, 5, 8
5, 8, 13
8, 13, 21
检查Gearman状态
最后,我们让工作程序运行,因此我们可以再次检查状态:
vagrant@localserver:~$ gearadmin --status
get_sequence 0 1 2
vagrant@localserver:~$ ps -aux | grep worker.php
root 4595 0.0 1.5 98928 7764 ? S 21:52 0:00 php /vagrant/tuts-gearman-supervisor/code/worker.php
root 4596 0.0 1.5 98928 7764 ? S 21:52 0:00 php /vagrant/tuts-gearman-supervisor/code/worker.php
每行中都有一个函数名称和三个数字:队列中的任务数(0),正在运行的作业数(1)和有能力的工作人员数(2)。
当然,要添加更多工作程序,您可以运行更多工作程序脚本。 要停止它们,可以使用killall
。 但是有一个很棒的工具来管理工人,它被称为主管。
关于主管的几句话
如手册所述:
Supervisor是一个客户端/服务器系统,允许其用户监视和控制类似UNIX的操作系统上的许多进程。
让我们安装它并创建基本配置文件:
sudo apt-get install supervisor
sudo nano /etc/supervisor/conf.d/supervisor.conf
在打开的编辑器中,我们将为Gearman worker创建基本配置:
[program:gearman-worker]
command=php /vagrant/tuts-gearman-supervisor/code/worker.php
autostart=true
autorestart=true
numprocs=3
process_name=gearman-worker-%(process_num)s
这将告诉主管,该工作程序必须在三个进程中运行,并在结束时重新启动。 现在保存配置文件,重新加载Supervisor,并检查正在运行的进程的状态:
vagrant@localserver:~$ sudo supervisorctl reload
Restarted supervisord
vagrant@localserver:~$ sudo supervisorctl status
gearman-worker:gearman-worker-0 RUNNING pid 4596, uptime 0:01:03
gearman-worker:gearman-worker-1 RUNNING pid 4595, uptime 0:01:03
gearman-worker:gearman-worker-2 RUNNING pid 4597, uptime 0:01:03
我们可以看到三个准备好从客户端脚本执行作业的工作人员。
结论
我们已经完成了安装和配置Gearman的基本任务。 现在您可以随意使用示例代码,因此请尝试对代码进行以下更改:
此外,您可以通过增加进程数量或在更快的服务器上运行它们来扩展工作人员的能力。 并且不要忘记使用Supervisor来使您的工作人员运转。
如有任何疑问,请随时在文章评论中提问。
翻译自: https://code.tutsplus.com/tutorials/making-things-faster-with-gearman-and-supervisor--cms-29337