繁体   English   中英

如何在 Swoole 工作人员/进程之间共享 PHP 对象

[英]How can I share PHP objects between Swoole workers/processes

我正在使用 Swoole 开发我自己的具有自定义逻辑的 WebSocket 服务器。 我为Swoole\WebSocket\Server制作了简单的包装器,并实现了一些用作事件处理程序的类。 这是包装器示例:

final class Server
{
    private WebSocketServer $server; // Alias used here, this is Swoole web socket server
    public Collection $articles;

    public function __construct()
    {
        $this->server = new WebSocketServer('0.0.0.0', 9501);
        $this->articles = new Collection;

        $openHandler = new OpenHandler($this, ...);
        $messageHandler = new MessageHandler($this);
        $closeHandler = new CloseHandler($this);

        $this->on(Event::Open, $openHandler);
        $this->on(Event::Message, $messageHandler);
        $this->on(Event::Close, $closeHandler);
    }

    public function run(): void
    {
        $this->server->start();
    }

    private function on(Event $event, callable $callback): void
    {
        $this->server->on($event->name, $callback);
    }
}

这是处理程序示例:

final class CloseHandler
{
    private Server $server;

    public function __construct(Server $server)
    {
        $this->server = $server;
    }

    public function __invoke(WebSocketServer $server, int $descriptor): void
    {
        $d = new Descriptor($descriptor);

        if (!$user = $this->server->articles->findUserByDescriptor($d)) {
            return;
        }

        $user->getDescriptors()->remove($d);

        echo "User {$user->getId()->asInt()} disconnected..." . PHP_EOL;
    }
}

问题是$this->server->articles似乎每次引发服务器事件时都指向不同的 object 实例。

我发现每次用户打开连接时,都会使用不同的 workerId 和 workerPid。 这可以以某种方式解释$this->server->articles问题。 我认为(但不确定)我可以将服务器配置为使用单个工作者和单个进程,但这可能会导致性能问题,所以情况并非如此。

我找到Swoole\Table class 但据我了解,它不能连续保存自己的副本。 我的意思是你可以在表格行中有STRINGINTFLOAT ,但不能有TABLE 我需要层次结构来表示这个结构:

  1. 申请有文章
  2. 单篇文章有一些元数据和用户
  3. 单用户有一些元数据和描述符(用于向客户端发送数据)

这种数据类型也有一些领域逻辑。 当然,我认为我可以使用Swoole\Table来实现它,但成本是多少?

所以我的问题是:如果可能的话,我如何在 Swoole WebSocket 服务器中共享 PHP 对象?

您可以使用PHP-DI自动装配您的 class,PHP-DI 将实例化您的类(如果之前未实例化)并在调用该方法时传递 class 实例。

或者您可以使用 static getter 来实现,如下所示:

文章.php

<?php

class Article
{
    private static Article $article;


    public static function getInstance(): Article
    {
        if (!isset(self::$article)) {
            self::$article = new Article();
        }

        return self::$article;
    }
}

CloseHander.php

<?php

class CloseHandler
{
    ...

    public function __invoke()
    {
        ...
        if (!$user = Article::getInstance()->findUserByDescriptor($d)) {
            return;
        }
        ...
    }
}

PHP-DI: https://php-di.org/doc/getting-started.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM