简体   繁体   中英

How can I share PHP objects between Swoole workers/processes

I am using Swoole to develop my own WebSocket server with custom logic. I've made simple wrapper for Swoole\WebSocket\Server and implemented some classes that work as event handlers. Here is wrapper example:

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);
    }
}

And here is handler example:

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;
    }
}

The thing is that it seems that $this->server->articles points to different object instance every time server event raised.

I found that every time user opens connection, different workerId and workerPid used. This can somehow explain $this->server->articles issue. I think (but not sure) I can configure server to use single worker and single process but this could lead to performance issues so this is not the case.

I found Swoole\Table class but as I understood it can't hold its own copy in a row. I mean you can have STRING , INT or FLOAT in table row but not TABLE . I need hierarchy to represent this structure:

  1. Application has articles
  2. Single article has some meta data and users
  3. Single user has some meta data and descriptors (used to send data to client)

This data types also have some domain logic. Sure I think I can implement it using Swoole\Table but what the cost?

So my question is: How can I share PHP objects inside Swoole WebSocket server if it is possible?

You can use PHP-DI to autowire your class, PHP-DI will instantiate your class(if not instantiated before) and pass the class instance whenever the method is invoked.

Or you can use static getter to achieve that, look below:

Article.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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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