PHP和pthreads3:根据条件将特定任务发送给工作人员

时间:2019-02-06 14:55:46

标签: php concurrency php-pthread

我想将多线程引入用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类会收到一条消息,并将其传递给负载最少的工作程序。所有工作人员应处于不同的线程中。您有任何想法如何以最佳方式完成此事吗?

0 个答案:

没有答案