我想将多线程引入用PHP编写的项目中。我发现pthreads是一个很好的库,可以满足我的需求。我将尝试以抽象的方式描述我的应用程序的工作过程,以便将该解决方案应用于具有相同体系结构的任何其他项目。
首先,我有一个消息队列,它由RabbitMQ提供。我有这些消息的验证过程。从队列中提取并验证消息后,我需要将其发送到我的外部应用程序之一。
我有一个负责交互的类(我们称之为EXT_APP) 通过套接字与外部应用程序一起使用。我还有一个类(我们称其为EXT_APP_DISPATCHER),它具有EXT_APPs池,当我完成验证消息时,我将其通过EXT_APP_DISPATCHER发送到EXT_APP且其通道数最少(不要为通道烦恼)每个EXT_APP都有一个函数,该函数提供的值描述了此外部应用程序现在加载的难易程度)
因此,我想使所有这些EXP_APP位于单独的线程中,因为有一些函数可以从套接字读取事件/向套接字写入事件,而这可能是提高应用程序性能的好时机。但是我如何根据其“负载”决定将验证后的消息发送到哪个线程。我清楚地了解到,我不能只调用位于另一个线程中的对象的函数。有一种实现或修改线程池的方法,因此我将根据其负载将消息发送到EXT_APP。
我确实写过课,所以您了解我在说什么:
class EXT_APP_DISPATCHER
{
private $connection_options = array(
array(
'host' => '127.0.0.1',
'scheme' => 'tcp://',
'port' => 5039,
'username' => 'asterisk_2',
'secret' => 'ajhu8dyvUWzV5JKa',
'connect_timeout' => 100,
'read_timeout' => 100
),
array(
'host' => '127.0.0.1',
'scheme' => 'tcp://',
'port' => 5038,
'username' => 'asterisk_1',
'secret' => 'DWSg33tCqwr7rXBk',
'connect_timeout' => 100,
'read_timeout' => 100
)
);
private $pool;
public function __construct()
{
$this->pool = new \Pool(2, EXT_APP::class, [$this->connection_options]);
}
public function processMessage($message): void
{
//todo Here I need to implement load balancing
//todo I need to get load from every worker and decide which one should receive task
$this->pool->submit(new TASK());
}
}
class EXT_APP extends \Worker
{
public static $counter = 0;
private $client;
public function __construct($options)
{
$this->client = new ClientImpl($options[self::$counter]);
self::$counter++;
$this->client->registerEventListener(function ($event)
{
echo 'Hey I received an event!';
});
$this->client->open();
}
public function run()
{
}
public function sendEvent($event)
{
$this->client->send($event);
}
public function getAmountOfBusyChannels()
{
$action = new CoreShowChannelsAction();
$actionResult = $this->client->send($action);
foreach ($actionResult->getEvents() as $eventMessage) {
if ($eventMessage instanceof CoreShowChannelsCompleteEvent) {
return $eventMessage->getKey('listitems');
}
}
return null;
}
}
class TASK extends \Threaded
{
public function run()
{
$this->worker->sendEvent(null);
}
}
/*
* EXT_APP_DISPATCHER initialization which is going to be located in main application class,
* so actually here before calling function processMessage
* I do receive message from RabbitMQ and validate it
*/
$ext_app_dispatcher = new EXT_APP_DISPATCHER();
$ext_app_dispatcher->processMessage(null);
$ext_app_dispatcher->processMessage(null);
我希望EXT_APP_DISPATCHER类会收到一条消息,并将其传递给负载最少的工作程序。所有工作人员应处于不同的线程中。您有任何想法如何以最佳方式完成此事吗?