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