0

我正在运行一个laravel websocket并通过 wss 建立连接。

我在服务器上运行命令,命令记录在一个文件中。每行也通过 websocket 发送到前端,以便我查看。每个 laravel-command 都有自己的文件和广播频道。

命令记录器:

class CommandLogger implements Logger {

    public $commandname = '';
    public $broadcast   = false;

    public function __construct($commandname, $broadcast = false) {
        $this->commandname = Str::camel(Str::slug($commandname));
        $this->broadcast = $broadcast;
    }

    function log($message) {
        $message = Carbon::now()->format('Y-m-d H:i:s').": ".$message;
        file_put_contents(storage_path("logs/commands/$this->commandname.log"), $message.PHP_EOL , FILE_APPEND | LOCK_EX);
        if($this->broadcast) {
            event(new CommandLogCreated($message, $this->commandname));
        }
    }
}

在 Vue.js 中,我使用 Echo(它实现了 pusherjs)收听:

Echo.private('logs.commands.' + command)
    .listen('.command-log:created', event => {
        this.log[command] += event.message + "\n";
        let splitLog = this.log[command].split("\n");
        let splitLength = splitLog.length;
        if(splitLength > 200) {
            splitLog = splitLog.slice(splitLength - 200, splitLength);
        }
        this.log[command] = splitLog.join('\n');
        this.trigger++;
    })
    .error(error => {
        console.log(error);
     });

我遇到的问题仅在命令发送大量消息以回显时发生。

以正常速率,消息之间有一些暂停,echo 执行乒乓球并且连接仍然接收消息。

在更高的消息速率下,似乎 echo 没有发送乒乓球,我的套接字默默地停止接收数据。在它停止接收后,它开始乒乓球,好像什么都没发生一样。服务器和客户端都没有断开连接。

Websocket 消息(注意它在 205000 处停止,没有错误并恢复乒乓球):

在此处输入图像描述

实际命令输出(在 230000 并且仍在运行):

在此处输入图像描述

如果我刷新页面,我会再次收到消息。

我已经直接更新了websockers:serve命令(vendor/beyondcode/laravel-websockets/src/Console/Commands/StartServer.php)并禁用了pongtracker:

protected function configurePongTracker()
{
    //$this->loop->addPeriodicTimer(10, function () {
    //    $this->laravel
    //        ->make(ChannelManager::class)
    //        ->removeObsoleteConnections();
    //});
}

然后我重新启动了 websocket 并再次尝试。这一次,无论我发送消息的速度有多快,echo 都会继续接收消息。

TL;博士:

我的结论是 echo 应该在从服务器接收消息之间进行乒乓球,因为目前它似乎无法这样做,并且 websocket 最终会清理连接而不会断开连接。如何强制 echo 进行乒乓球,或者确保服务器不清理连接而不冒连接失控的风险?

更新 1:

我一直在深入研究该Startserver.php文件并发现了这一点:

public function removeObsoleteConnections(): PromiseInterface
{
    if (! $this->lock()->acquire()) {
        return Helpers::createFulfilledPromise(false);
    }

    $this->getLocalConnections()->then(function ($connections) {
        foreach ($connections as $connection) {
            $differenceInSeconds = $connection->lastPongedAt->diffInSeconds(Carbon::now());

            if ($differenceInSeconds > 120) {
                $this->unsubscribeFromAllChannels($connection);
            }
        }
    });

    return Helpers::createFulfilledPromise(
        $this->lock()->forceRelease()
    );
}

这就解释了为什么我停止接收消息,但没有断开连接。它只是取消订阅我正在静默收听的频道(在前端看不到这个)并保持连接活跃。

我还在github(laravel/echo) 上创建了一个问题,因为我确实认为这是不受欢迎的行为。我只是不确定问题出在 echo 还是 pusher js 中。

4

1 回答 1

0

我经历过这个。检查您的频道名称和类型,并确保您有权访问。app.js另外,请检查是否没有其他 js文件像我发生的那样干扰您的文件。检查这个laracasts问题

于 2021-04-16T18:16:42.093 回答