Ratchetphp websocket error in server related with load balancer

Viewed 16

I have issue with websocket when using load balancer . We have 3 three different servers which using same php packages. When user connects to websocket proxy redirect user to any working (example. A server, A1 user) server. Then php server creates new Resource contained user resource id , remote address and some informations. When other users connects then proxy redirect user another server (example. B server B1 user )and this process repeat again. But this time resource belongs to antother server (example. B server). Problem is there.. When we need emit message from A1 user to B1 , server can't find B1 user, because his resource located in A server.

How to can i connect this user whith one another ??

Code is such:

<?php

namespace App\Lib\Notify;

use App\Lib\Notify\Messages\SocketMessagesFactory;
use App\Models\Mongo\CacheRequest;
use App\Models\TwoFactorAuth;
use Illuminate\Support\Facades\Redis;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use React\EventLoop\Loop;
use React\EventLoop\LoopInterface;

class SocketServer implements MessageComponentInterface
{
    use SocketAuth, SocketBind,SocketCLIMessages;

    protected $redis;
    public static $clients;
    public static $localClients;


    public function __construct()
    {
        $this->redis = Redis::connection();

        /* Deleting all users from redis related old session */
        self::getKeysLoop('users:*', function ($user, $index) {
            $this->redis->del($index);
        });

        /* Deleting all confirmation reqeusts */
        self::getKeysLoop('confirm:*', function ($user, $index) {
            $this->redis->del($index);
        });

        TwoFactorAuth::truncate();
        CacheRequest::truncate();

        echo self::datetime()."\033[34mDeleted all cached users from online (redis) \033[0m \n";
    }

    /*
     * When connection opened
     * */
    public function onOpen(ConnectionInterface $conn)
    {
        $query = $conn->httpRequest->getUri()->getQuery();
        parse_str($query, $queryArr);
        echo self::datetime(). "Connecting ip: ".$conn->remoteAddress." ... \n";
             
        $auth = self::checkToken(($queryArr['token']) ?? null);

            if ($auth['success']) {
                $user = $this->redis->hgetall('users:' . $auth['user']->data->userId);

                /* Append to online */
                if ($user) {
                    #$this->usersCount[$auth['user']->data->userId]++;
                    echo self::datetime().'Push resource to exist user : (userID: '.$auth['user']->data->userId.' )' . "\n";
                    self::pushToArr('users:' . $auth['user']->data->userId, $user, 'resources', $conn->resourceId);
                } else {

                    echo self::datetime().'Connected user (id: '.$auth['user']->data->userId.') ' . "\n";
                    $conn->send('Welcome from Wesocket ! Successfully connection.');
                    /* Binding to session  */
                    self::bindUser($conn,$queryArr['token'],$auth);
                }

                /* Bind to general line */
                self::$clients[$conn->resourceId] = $conn;
            }else{

                /* Close when bad authorized */
                $conn->close();
                echo self::datetime()."Error in auth: " . $auth['message'] . "\n";
            }
        
    }

    /*
    * When message from users
    * */
    public function onMessage(ConnectionInterface $conn, $msg)
    {
        if(is_string($msg)) {
            $message = json_decode($msg);
            if(json_last_error()===JSON_ERROR_NONE) {
                if(isset($message->type) && is_string($message->type) && method_exists(SocketMessagesFactory::class,$message->type)) {
                    $method = $message->type;
                    SocketMessagesFactory::$method($message,$conn);
                }
            }
        }
    }


    public function onClose(ConnectionInterface $conn)
    {
        self::controllableLogout($conn);
        unset(self::$clients[$conn->resourceId]);
        unset(self::$localClients[$conn->resourceId]);
        echo self::datetime()."Connection closed for ({$conn->remoteAddress}) " . $conn->resourceId . "\n";
        #print_r( self::findUserByResource($conn->resourceId));
    }


    public function onError(ConnectionInterface $conn, \Exception $e)
    {
        echo self::datetime()."Error message: " . (string)$e->getMessage() . "\n";
        $conn->close();
    }

0 Answers
Related