Laravel Echo服务器在生产服务器上无法工作

11

我使用laravel echo作为广播器时,遇到了socket.io的问题。

我尝试的方法:

php artisan cache:clear
php artisan config:clear

我可以在日志中看到用户的连接:

0|Socket-Connection  | [11:17:00 AM] - ********** joined channel: test-channel
0|Socket-Connection  | [11:17:01 AM] - ********** authenticated for: private-user.1
0|Socket-Connection  | [11:17:01 AM] - ********** joined channel: private-user.1

我的队列正在运行,并且可以正确记录所有事件。

我可以在Redis控制台中完美地看到我的事件和数据库通知。

但是没有事件被广播,我在laravel-echo-server控制台中也没有看到它们。 在我的本地环境中一切正常,但在生产环境中却无法工作,让我感到非常苦恼。

这是我的 Laravel Echo JS:

if (typeof io !== 'undefined') {
    console.log(window.location.origin);
    window.Echo = new Echo({
        broadcaster: 'socket.io',
        host: window.location.origin + ':6001',
        auth: {
            headers: {
                Authorization: 'Bearer ' + bearerToken,
            },
        }
    });
    window.Echo.private('user.' + user_id).notification((notification) => {
        console.log(notification);
    });
}

在我的用户模型中,我定义了这个:

/**
* @return string
*/
public function receivesBroadcastNotificationsOn()
{
    return 'user.' . $this->id;
}

而在我的频道中,我有这个:

Broadcast::channel('user.{id}', function ($user, $id) {
    return (int)$user->id === (int)$id;
});
这是我的回显服务器配置,所有路径都正确。我已在本地主机上测试了相同的文件并且一切正常:

这是我的回显服务器配置,所有路径都是正确的。我已经在我的本地主机上测试了同样的文件,一切都正常:

var echo = require('laravel-echo-server/dist');

echo.run({
    "appKey": "myappkey",
    "authHost": "https://url",
    "authEndpoint": "/broadcasting/auth",
    "database": "redis",
    "clients": [
        {
            "appId": "myappid",
            "key": "mykey"
        }
    ],
    "databaseConfig": {
        "redis": {
            "port": "6379",
            "host": "myhost",
            "password": "mysupersecretpassword"
        },
        "sqlite": {
            "databasePath": "/database/laravel-echo-server.sqlite"
        }
    },
    "devMode": true,
    "host": "url",
    "port": "6001",
    "protocol": "https",
    "referrers": [],
    "sslCertPath": "/path/to/certificate.pem",
    "sslKeyPath": "/path/to/key",
    "verifyAuthPath": true,
    "verifyAuthServer": false
});

当我发布数据库通知时,我的Redis日志显示了这个:

1534840681.110359 [0 "IP ADDRESS HERE"] "PUBLISH" "private-user.2" "{\"event\":\"Illuminate\\\\Notifications\\\\Events\\\\BroadcastNotificationCreated\",\"data\":{\"title\":\"Ravim CONVULEX 50MG\\/ML  staatust muudeti\",\"notification_type\":\"element-soft-delete\",\"message\":\"Ravimi CONVULEX 50MG\\/ML  staatust muutis kasutaja Kalle \",\"url\":\"https:\\/\\/www.app.riskomed.com\\/admin\\/brands\\/all\",\"id\":\"30c37d0d-c39b-41bf-93fc-afa0c78ca9db\",\"type\":\"App\\\\Notifications\\\\API\\\\Management\\\\Medical\\\\Brands\\\\BrandSoftDeleteNotification\",\"socket\":null},\"socket\":null}"

编辑

这是我的通知

        /**
     * Get the notification's delivery channels.
     *
     * @param  mixed $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail', 'database', 'broadcast'];
    }

@Miguel 我可以在哪里做到这个? - z0mbieKale
当您在本地测试时,是否在echo.run()中使用了与生产环境相同的authHosthostport设置?我想知道这是否是防火墙或类似访问问题... - Rich
@raqulka 我猜你的队列服务器在生产环境中没有运行。执行 artisan queue:restart 命令,检查是否可以解决你的问题... - Bart
@raqulka,你的服务器日志里有什么信息? - Bart
@raqulka 在放弃了几天后重新审视这个问题,我发现我在自己的情况下犯了两个愚蠢的错误。.env文件中的广播驱动程序被设置为'log',而且我忘记在Mac和Ubuntu机器上都安装sqlite3。虽然如此,还是感谢你的回复和建议,我非常感激。 - Dev
显示剩余7条评论
2个回答

2

我看到您在生产服务器上使用了'https'协议,因此您需要定义'sslCertPath'和'sslKeyPath':

来自文档

使用SSL运行

  • 您的客户端实现必须从https访问socket.io客户端。
  • 服务器配置必须将服务器主机设置为使用https。
  • 服务器配置应包括指向位于服务器上的ssl证书和密钥的路径。

已经完成了。通过 SSL 进行。我只写了 "path/to",因为我不想暴露我的服务器路径。 - z0mbieKale
好的,我在日志中看到你正在监听“private-user.1”频道,但是Redis在日志中广播到“PUBLISH”“private-user.2”,这可能会有问题吗? - Denis Kuratovich
两个用户在线,因此是用户2。 - z0mbieKale

1
如果您看到用户加入频道,那么很可能已经正确设置。您只需要广播通知才能使您的console.log(notification)调用起作用,因为您正在特定地在用户频道上调用通知函数。有关更多详细信息,请参见https://laravel.com/docs/5.6/broadcasting#notifications
使用通知进行广播:
//Create a new notification with artisan, e.g. php artisan make:notification testNotification

class testNotification extends Notification {

    ...

    public function via($notifiable)
    {
        return ['broadcast'];
    }

    ...

    public function toBroadcast($notifiable) {
        return new BroadcastMessage([
            'message' => 'TEST',
        ]);
    }
}

当您准备好广播您的信息时,只需通知用户:

$user->notify(new testNotification());

编辑:

另外,请确保您的用户模型中有 Notifiable 特性:

class User extends Authenticatable
{
    use Notifiable;

    ...
}

请确保在您的通知类中定义了 toBroadcast($notifiable) 函数并返回一个 BroadcastMessage,因为我在您的编辑中没有看到它。您需要以要测试的用户身份登录并导航到您调用 Echo 通知的页面,然后设置一个测试路由来调用 $user->notify(new testNotification()); 并在另一个窗口/选项卡中访问该页面。 - JPark
另外,请确保您的用户模型具有“Notifiable”特质。 - JPark
它具有可通知的特性! - z0mbieKale

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接