Laravel Websocket 结合 Nuxt 和 Nginx 反向代理返回 502。

3

我正在运行 Laravel 7,并尝试使用 Nginx 代理和 SSL 运行 Laravel-Websockets。不幸的是,在我配置好一切之后,我遇到了以下问题:

WebSocket 连接至 'wss://www.rabter.com:6001/app/174e625ceea907e9e63c?protocol=7&client=js&version=4.3.1&flash=false' 失败:WebSocket 握手期间出错:意外的响应代码:502

在实施 SSL 之前,一切都正常工作。

/config/websockets.php

use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize;

return [

    'dashboard' => [
        'port' => env('LARAVEL_WEBSOCKETS_PORT', 6001),
    ],

    'apps' => [
        [
            'id' => env('PUSHER_APP_ID'),
            'name' => env('APP_NAME'),
            'key' => env('PUSHER_APP_KEY','174e625ceea907e9e63c'),
            'secret' => env('PUSHER_APP_SECRET'),
            'path' => env('PUSHER_APP_PATH'),
            'capacity' => null,
            'enable_client_messages' => true,
            'enable_statistics' => true,
        ],
 ],
    'app_provider' => BeyondCode\LaravelWebSockets\Apps\ConfigAppProvider::class,
   'allowed_origins' => [
        //
    ],
 'max_request_size_in_kb' => 250,
 'path' => 'laravel-websockets',
 'middleware' => [
        'web',
            'api',
        Authorize::class,
    ],

    'statistics' => [

        'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,

        'interval_in_seconds' => 60,
          'delete_statistics_older_than_days' => 60,
        'perform_dns_lookup' => true,
    ],

    'ssl' => [

        'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),
        'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),
        'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
    ],
    'channel_manager' => \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager::class,
];
`
/config/broadcasting.php
`
'default' => env('BROADCAST_DRIVER', 'pusher'),
 'connections' => [
        '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',
            ],
        ],
        'redis' => [
            'driver' => 'redis',
            'connection' => 'default',
        ],
        'log' => [
            'driver' => 'log',
        ],
        'null' => [
            'driver' => 'null',
        ],
    ],
];

/etc/nginx/conf.d/vhosts/rabter.com.ssl.conf

  listen 45.82.136.131:443 ssl;
    server_name rabter.com;
        return 301 https://www.rabter.com$request_uri;

}
server {
    listen 45.82.136.131:443 ssl;
    server_name www.rabter.com;
    ssl_certificate /etc/pki/tls/certs/rabter.com.bundle;
    ssl_certificate_key /etc/pki/tls/private/rabter.com.key;
      root /home/rabter/core/public/;
        index index.php;
        access_log /var/log/nginx/rabter.com.bytes bytes;
       access_log /var/log/nginx/rabter.com.log combined;
      error_log /var/log/nginx/rabter.com.error.log error;

location / {
    proxy_set_header                Connection "keep-alive";
    proxy_set_header                Upgrade $http_upgrade;
    proxy_set_header                Connection 'upgrade';
    proxy_http_version              1.1;
    proxy_pass                      https://45.82.136.131:3000$uri;
    proxy_connect_timeout            300;
    proxy_send_timeout               300;
    proxy_read_timeout               300;
    send_timeout                     300;
    proxy_intercept_errors on;
    error_page                      404 = @php;

proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}

location @php {
    try_files                       $uri $uri/  /index.php?$query_string;
}


location ~ \.php$ {
    fastcgi_split_path_info         ^(.+\.php)(/.+)$;
    fastcgi_pass                    45.82.136.131:9000;
    fastcgi_index                   index.php;
    include                         fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_intercept_errors        off;
    fastcgi_buffer_size             16k;
    fastcgi_buffers                 4 16k;
    fastcgi_connect_timeout         300;
    fastcgi_send_timeout            300;
    fastcgi_read_timeout            300;
 proxy_http_version 1.1;
   proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;

}

}
    upstream websocket {
        server 127.0.0.1:6001;

    }

    server {

        listen 6001 ssl;
        ssl_certificate /etc/myssl/certs/rabter.com.bundle;
        ssl_certificate_key etc/myssl/private/rabter.com.key;

        location / {
            proxy_pass https://websocket;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
        proxy_connect_timeout 43200000;
        }
    }

Laravel-Echo 配置

      broadcaster: 'pusher',
      key: process.env.MIX_PUSHER_APP_KEY,
      cluster: process.env.MIX_PUSHER_APP_CLUSTER,
      wsHost:'rabter.com',
      wsPort:6001,
      wssPort: 6001,
      disableStats: true,
      encrypted: true,
      authEndpoint: process.env.CLIENT_URL + '/api/broadcasting/auth',
      enabledTransports: ['ws', 'wss'],
    }],

我正在使用nuxtjs作为前端技术,这个问题困扰了我一个多月。

非常感谢您的任何帮助。


502 表示 nginx 无法连接到套接字。在我看来这是有道理的,因为据我所知,您已经将 nginx 和套接字都设置为监听 6001 端口,但只有一个能够占用该端口。 - apokryfos
你能详细说明一下吗?或者提供正确的配置文件。谢谢。 - Pc Monk
你有 listen 6001 ssl,但你也有 wsPort:6001。尝试使用 wsPort:6002 作为示例,然后在你的 nginx 配置中添加 server 127.0.0.1:6002;。但是请确保在从外部连接到 websocket 时连接到 6001(即 Laravel 配置可能保持不变)。 - apokryfos
那么你的意思是laravel-websocket和nginx不应该在同一个端口上吗?我已经设置了wsPort:6002wssPort:6002,还有upstream websocket {server 127.0.0.1:6002;},我在location /中使用它。重启nginx和npm后,我得到了WebSocket is closed before the connection is established.的错误信息。但它一直在尝试连接,第二个错误始终是Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT。我还添加了proxy_send_timeout 43200000;proxy_read_timeout 43200000; proxy_connect_timeout 43200000;} - Pc Monk
1个回答

2

我现在的配置正在使用ssl,所以我会分享每个文件。我会在最后简要解释一下。

在开始之前,请确保您已经从YOUR_SITE_NAME.YOUR_DOMAIN_SUFFIX.ssl.conf复制了自己的完整ssl_ciphers(如果有的话)。

Laravel V8,LaravelWebSocket版本1.4,pusher 4.0

Websockets.php:

<?php

use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize;

return [

    /*
     * Set a custom dashboard configuration
     */
    'dashboard' => [
        'port' => env('LARAVEL_WEBSOCKETS_PORT', 6001),
    ],

    /*
     * This package comes with multi tenancy out of the box. Here you can
     * configure the different apps that can use the webSockets server.
     *
     * Optionally you specify capacity so you can limit the maximum
     * concurrent connections for a specific app.
     *
     * Optionally you can disable client events so clients cannot send
     * messages to each other via the webSockets.
     */
    'apps' => [
        [
            'id' => env('PUSHER_APP_ID'),
            'name' => env('APP_NAME'),
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'path' => env('PUSHER_APP_PATH'),
            'capacity' => null,
            'enable_client_messages' => true,
            'enable_statistics' => true,
        ],
    ],

    /*
     * This class is responsible for finding the apps. The default provider
     * will use the apps defined in this config file.
     *
     * You can create a custom provider by implementing the
     * `AppProvider` interface.
     */
    'app_provider' => BeyondCode\LaravelWebSockets\Apps\ConfigAppProvider::class,

    /*
     * This array contains the hosts of which you want to allow incoming requests.
     * Leave this empty if you want to accept requests from all hosts.
     */
    'allowed_origins' => [
        //
    ],

    /*
     * The maximum request size in kilobytes that is allowed for an incoming WebSocket request.
     */
    'max_request_size_in_kb' => 250,

    /*
     * This path will be used to register the necessary routes for the package.
     */
    'path' => 'laravel-websockets',

    /*
     * Dashboard Routes Middleware
     *
     * These middleware will be assigned to every dashboard route, giving you
     * the chance to add your own middleware to this list or change any of
     * the existing middleware. Or, you can simply stick with this list.
     */
    'middleware' => [
        'web',
            'api',
        Authorize::class,
    ],

    'statistics' => [
        /*
         * This model will be used to store the statistics of the WebSocketsServer.
         * The only requirement is that the model should extend
         * `WebSocketsStatisticsEntry` provided by this package.
         */
        'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,

        /*
         * Here you can specify the interval in seconds at which statistics should be logged.
         */
        'interval_in_seconds' => 60,

        /*
         * When the clean-command is executed, all recorded statistics older than
         * the number of days specified here will be deleted.
         */
        'delete_statistics_older_than_days' => 60,

        /*
         * Use an DNS resolver to make the requests to the statistics logger
         * default is to resolve everything to 127.0.0.1.
         */
        'perform_dns_lookup' => false,
    ],

    /*
     * Define the optional SSL context for your WebSocket connections.
     * You can see all available options at: http://php.net/manual/en/context.ssl.php
     */
    'ssl' => [
        /*
         * Path to local certificate file on filesystem. It must be a PEM encoded file which
         * contains your certificate and private key. It can optionally contain the
         * certificate chain of issuers. The private key also may be contained
         * in a separate file specified by local_pk.
         */
        'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),

        /*
         * Path to local private key file on filesystem in case of separate files for
         * certificate (local_cert) and private key.
         */
        'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),

        /*
         * Passphrase for your local_cert file.
         */
        'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
        
     // 'verify_peer' => false,
    ],

    /*
     * Channel Manager
     * This class handles how channel persistence is handled.
     * By default, persistence is stored in an array by the running webserver.
     * The only requirement is that the class should implement
     * `ChannelManager` interface provided by this package.
     */
    'channel_manager' => \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager::class,
];

broadcasting.php:

<?php

return [


    'default' => env('BROADCAST_DRIVER', 'pusher'),

  
    'connections' => [
        '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',
        'encrypted' => true,
 
            ],
        ],

        'redis' => [
            'driver' => 'redis',
            'connection' => 'default',
        ],

        'log' => [
            'driver' => 'log',
        ],

        'null' => [
            'driver' => 'null',
        ],

    ],

];

nuxt.config.js:


      buildModules: [
    //The start of part that must be included in your buildModules
        ['@nuxtjs/laravel-echo',{
          broadcaster: 'pusher',
          key: process.env.MIX_PUSHER_APP_KEY,
          cluster: process.env.MIX_PUSHER_APP_CLUSTER,
          wsHost:'www.example.com',
          wsPort:6001,
          wssPort:6001,
          enabledTransports: ['ws', 'wss'],
          disableStats: true,
          encrypted: true,
        }]
        //End
         ]

Nginx YOUR_SITE_NAME.YOUR_DOMAIN_SUFFIX.ssl.conf:

           
          server {
          listen zzz:zzz:zzz:zzz:443 ssl http2;
          server_name example.com;
              return 301 https://www.example.com$request_uri;
       }
       server {
          listen zzz:zzz:zzz:zzz:443 ssl http2;
          server_name www.example.com;
          ssl_certificate /etc/pki/tls/certs/example.bundle;
          ssl_certificate_key /etc/pki/tls/private/example.key;
          ssl_session_timeout       5m;
           ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
          ssl_ciphers YOUR CIPHERS
        ssl_prefer_server_ciphers   on;
        root /home/example/core/public/;
        index index.php;
        access_log /var/log/nginx/example.com.bytes bytes;
        access_log /var/log/nginx/example.com.log combined;
        error_log /var/log/nginx/example.com.error.log error;
    
    location / {
      proxy_set_header                Connection "keep-alive";
        proxy_set_header                Upgrade $http_upgrade;
        proxy_set_header                Connection 'upgrade';
        proxy_http_version              1.1;
        proxy_pass                    https://zzz:zzz:zzz:zzz:3000$uri;
        proxy_connect_timeout            300;
        proxy_send_timeout               300;
        proxy_read_timeout               300;
        send_timeout                     300;
    
    
    }
    
        location @php {
        try_files                       $uri $uri/  /index.php?$query_string;
      }
    
      location ~ \.php$ {
        fastcgi_split_path_info         ^(.+\.php)(/.+)$;
        fastcgi_pass                    127.0.0.1:9000;
        fastcgi_index                   index.php;
        include                         fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_intercept_errors        off;
        fastcgi_buffer_size             16k;
        fastcgi_buffers                 4 16k;
        fastcgi_connect_timeout         300;
        fastcgi_send_timeout            300;
        fastcgi_read_timeout            300;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_intercept_errors on;
        error_page                      404 = @php;
    
    }
    
    location ~ /app/ {
        return 404;
    }
    }

Nginx YOUR_SITE_NAME.YOUR_DOMAIN_SUFFIX.conf:

server {
  listen zzz.zzz.zzz:80;
    server_name example.com www.example.com;
        return 301 https://www.example.com$request_uri;

}


如果您在运行CentOS 7,则可以尝试将以下代码复制到终端中:cd /etc/nginx/conf.d/vhosts,然后按回车并输入ls。您会看到YOUR_SITE_NAME.YOUR_DOMAIN_SUFFIX.conf和YOUR_SITE_NAME.YOUR_DOMAIN_SUFFIX.ssl.conf两个文件。
请注意,在这两个文件中,您都需要将example更改为您的域名,并将zzz更改为服务器的IP地址。如果您的Internet IP地址无效,也可以尝试使用127.0.0.1。
请检查rootlogs地址,因为它们可能与我的不同。 fastcgi_pass也可以是localIP或internetIP,对我而言,在进行后端/前端/服务器更新之前它是internetIP,但现在是localIP。
设置完成后,请确保重启nginx和websocket服务,并执行php artisan cacheconfig clear命令,然后进行一次新的nuxt build,并通过链接https://www.example.com/laravel-websockets连接到您的laravel-websockets。
我使用此配置来为nginx+nuxtjs+laravel+laravel-websocket+pusher配置SSL站点。
希望这个答案能够帮助您成功连接。

你是否需要在.env文件中设置变量LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT?还是它会自动解决?谢谢! - Dante
1
你必须在你的.env文件中设置它。 - Pc Monk
谢谢,问题已解决!我在.env文件中添加了以下内容: LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT=storage/certificates/websocket/certificate.crt LARAVEL_WEBSOCKETS_SSL_LOCAL_PK=storage/certificates/websocket/key.key - Dante

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