3

软件:

在 websockets.php (完整文件)中,我有我的证书local_certlocal_pk设置了我的证书。如果我将此选项留空,我什至无法连接。我也设置verify_peerfalse,因为如果我不这样做,我也无法连接。

广播.php:

'pusher' => [
        'driver' => 'pusher',
        'key' => env('PUSHER_APP_KEY'),
        'secret' => env('PUSHER_APP_SECRET'),
        'app_id' => env('PUSHER_APP_ID'),
        'options' => [
            'cluster' => env('PUSHER_APP_CLUSTER'),
            'host' => '127.0.0.1',
            'port' => 6001,
            'scheme' => 'https',
            'curl_options' => [
                CURLOPT_SSL_VERIFYHOST => 0,
                CURLOPT_SSL_VERIFYPEER => 0,
            ]
        ],
    ],

如果我摆脱 curl 选项,我会得到一个空的 Broadcast 异常,如此处所述

bootstrap.js:

window.Pusher = require('pusher-js');
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: '7d23096ae0ab2d02d220',
    wsHost: window.location.hostname,
    wsPort: 6001,
    wssPort: 6001,
    encrypted: true,
    disableStats: true,
    auth: {
        headers: {
            'X-CSRF-TOKEN': window.App.csrfToken,
        },
    },
})

这是我在运行后从日志中得到的全部内容php artisan websockets:serve

New connection opened for app key 7d23096ae0ab2d02d220.
Connection id 49092664.114416323 sending message {"event":"pusher:connection_established","data":"{\"socket_id\":\"49092664.114416323\",\"activity_timeout\":30}"}

我应该得到的是关于收听/加入频道和发送消息等的消息。但目前所有这些都不起作用。我有这样的事情:

Echo.private('notifications.' + this.user.id)
                .listen('UserNotificationSent', (e) => {
                    console.log(e)
                })

事件:例如UserNotificationSent.php

当然,在内部,我还设置了其他所有内容:带有身份验证的频道等。一切都在我的机器上本地运行,在较低的 Laravel 版本(5.4)上。但是我最近更新到 5.8 并部署到服务器上,现在我为此苦苦挣扎。

我还在github 上打开了一个问题

重要更新 这实际上不是由于部署,我在本地设置中遇到了同样的问题。有趣的是,通过Echo.channel()作品收听频道.private()是行不通的。在 Github(上面的链接)上,我遇到了一个有完全相同问题的人。我们还没有找到解决方案。

4

3 回答 3

1

发生这种情况是因为在实时服务器上的 nginx 中保留了端口 6001(底部有说明)。我需要在 nginx 上使用反向代理来使其工作 - 并使用端口 6002 用于实时服务器中的 websockets。

nginx 中(根据要求,我添加了完整的 nginx 代码)

server {

  #The nginx domain configurations
  root /var/www/laravel/public;
  index index.html index.htm index.php index.nginx-debian.html;
  server_name example.com www.example.com;

  #WHAT YOU NEED IS FROM HERE...
  location / {
      try_files $uri $uri/ /index.php?$query_string;

      # "But why port 6000, 6002 and 433? Scroll at the bottom"

      proxy_pass                          http://127.0.0.1:6001;
      proxy_set_header Host               $host;
      proxy_set_header X-Real-IP          $remote_addr;

      proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto  https;
      proxy_set_header X-VerifiedViaNginx yes;
      proxy_read_timeout                  60;
      proxy_connect_timeout               60;
      proxy_redirect                      off;

      # Specific for websockets: force the use of HTTP/1.1 and set the Upgrade header
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection 'upgrade';
      proxy_set_header Host $host;
      proxy_cache_bypass $http_upgrade;
 }
 #..UNTIL HERE - The rest are classic nginx config and certbot

 #The default Laravel nginx config
 location ~ \.php$ {
      try_files $uri =404;
      fastcgi_split_path_info ^(.+\.php)(/.+)$;
      fastcgi_pass unix:/run/php/php7.2-fpm.sock;
      fastcgi_index index.php;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      include fastcgi_params;
 }

 #SSL by certbot
 listen [::]:443 ssl ipv6only=on; # managed by Certbot
 listen 443 ssl; # managed by Certbot

 ssl                         on;
 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
 ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
 include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
 ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

 ssl_session_cache           shared:SSL:30m;
 ssl_protocols               TLSv1.1 TLSv1.2;

 # Diffie Hellmann performance improvements
 ssl_ecdh_curve              secp384r1;
}

通过 TLS 连接到您的域的所有内容都将以纯文本形式代理到端口 6001 上的本地服务。这会将所有 TLS(和证书管理)卸载到 Nginx,使您的 websocket 服务器配置尽可能干净和简单。

这也使通过 Let's Encrypt 的自动化变得更加容易,因为已经有一些实现可以管理 Nginx 中的证书配置并在需要时重新加载它们。-资料来源 - Mattias Geniar

回声设置:

let isProduction = process.env.MIX_WS_CONNECT_PRODUCTION === 'true';

Vue.prototype.Echo = new LaravelEcho({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    wssHost: window.location.hostname,
    wssPort: isProduction ? 6002 : 6001,
    wsHost: window.location.hostname,
    wsPort: isProduction ? 6002 : 6001,
    disableStats: false,
    encrypted: isProduction,
    enabledTransports: ['ws', 'wss'],
    disabledTransports: ['sockjs', 'xhr_polling', 'xhr_streaming']
});

websockets.php中

'apps' => [
    [
        'id' => env('MIX_PUSHER_APP_ID'),
        'name' => env('APP_NAME'),
        'key' => env('MIX_PUSHER_APP_KEY'),
        'secret' => env('MIX_PUSHER_APP_SECRET'),
        'enable_client_messages' => false,
        'enable_statistics' => true,
    ],
],

// I kept them null but I use LetsEncrypt for SSL certs too.
'ssl' => [
   'local_cert' => null,
   'local_pk' => null,
   'passphrase' => null,
]

广播.php

'pusher' => [
     'driver' => 'pusher',
     'key' => env('MIX_PUSHER_APP_KEY'),
     'secret' => env('MIX_PUSHER_APP_SECRET'),
     'app_id' => env('MIX_PUSHER_APP_ID'),
     'options' => [
         'cluster' => env('MIX_PUSHER_APP_CLUSTER'),
         'encrypted' => env('MIX_WS_CONNECT_PRODUCTION'),
         'host' => '127.0.0.1',
         'port' => env('MIX_WS_CONNECT_PRODUCTION') ? 6002 : 6001,
         'scheme' => 'http'
     ],
 ],

这是我让它工作的完整周期。希望能帮助到你。


引用Alex Bouma 的解释

“可是为什么是6000、6002和433端口,什么乱七八糟的!?”

我听到了!让我解释一下,希望以后一切都有意义。

事情是这样的,在您的服务器上打开一个端口一次只能由一个应用程序完成(从技术上讲,这不是真的,但让我们在这里保持简单)。因此,如果我们让 NGINX 在端口 6001 上侦听,我们也无法在端口 6001 上启动我们的 websockets 服务器,因为它会与 NGINX 冲突,反之亦然,因此我们让 NGINX 在端口 6002 上侦听并让它代理(NGINX 是反向代理毕竟)所有通过普通 http 到端口 6001(websockets 服务器)的流量。剥离 SSL,因此 websockets 服务器无需知道如何处理 SSL。

因此,NGINX 将处理所有 SSL 魔法,并将普通 http 的流量转发到您的服务器上的端口 6001,websockets 服务器正在该端口监听请求。

我们没有在 websockets.php 配置中配置任何 SSL 并且我们在 broadcasting.php 中将方案定义为 http 并使用端口 6001 的原因是绕过 NGINX 并直接在本地与 websockets 服务器通信,而不需要更快(更容易)的 SSL配置和维护)。

于 2019-11-16T11:44:26.753 回答
1

我发现了问题。

我有这个web.php

Route::post('/broadcasting/auth', function (Illuminate\Http\Request $req) {
if ($req->channel_name == 'users') {
    return Broadcast::auth($req);
}
});

我不完全记得为什么以及何时添加它,但它可能来自这里。由于某种原因,这没有产生任何错误。无论如何,我摆脱了这个,现在它就像一个魅力。

于 2019-11-19T11:49:21.990 回答
-3

对事件使用 broadcastAs() 方法

public function broadcastAs()
{
    return 'UserNotificationSent';
}

像这样听。

.listen('.UserNotificationSent', function (e) {
    ....
});

将 dot(.) 放在 UserNotificationSent 事件之前以监听它

见这里https://laravel.com/docs/6.x/broadcasting#broadcast-name

于 2019-11-15T16:26:28.440 回答