You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native无法连接DigitalOcean上Laravel的Soketi Pusher服务器求助

Laravel + Soketi + React Native 连接失败排查

在DigitalOcean的Ubuntu服务器部署了Laravel应用与Soketi服务器,React Native应用无法连接,以下是配置信息与错误日志,附排查方案:

broadcasting.php 配置

'pusher' => [
    'driver' => 'pusher',
    'key' => env('PUSHER_APP_KEY'),
    'secret' => env('PUSHER_APP_SECRET'),
    'app_id' => env('PUSHER_APP_ID'),
    'log' => true,
    'options' => [
        'host' => env('PUSHER_HOST', '127.0.0.1'),
        'port' => env('PUSHER_PORT', 6001),
        'scheme' => env('PUSHER_SCHEME', 'http'),
        'encrypted' => true,
        'useTLS' => env('PUSHER_SCHEME') === 'https',
        'curl_options' => [
            CURLOPT_SSL_VERIFYHOST => 0,
            CURLOPT_SSL_VERIFYPEER => 0,
        ],
    ],
],

.env 变量(已修改凭据)

PUSHER_APP_KEY="9b9a489dffdf0c38f28f43777"
PUSHER_APP_SECRET="26574dsfsfsf57220cf042bd77"
PUSHER_APP_ID="13023345464644"
PUSHER_APP_CLUSTER="eu"

# SOKETI SERVER DETAILS
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_SCHEME=https

React Native Echo 启动代码

Pusher.logToConsole = true;
let myIp = 'laraapp.com';
let port = 6001;
let options = {
    key: env.PUSHER_APP_KEY,
    wsHost: myIp,
    wsPort: port,
    wssPort: port,
    enableStats: true,
    logToConsole: true,
    encrypted: true,
    forceTLS: false,
    enabledTransports: ['ws', 'wss'],
};

let PusherClient = new Pusher(options.key, options);
PusherClient.connection.bind('error', () => console.log('PusherClient::error', arguments));

const echo = new Echo({
    broadcaster: 'pusher',
    client: PusherClient,
    ...options
});

Supervisor 配置(启动 Soketi)

[program:soketi]
process_name=%(program_name)s_%(process_num)02d
command=soketi start 
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=Gabotron
numprocs=1
redirect_stderr=true
stderr_logfile=/home/Gabotron/logs/soketi.err.log
stdout_logfile=/home/Gabotron/logs/soketi.out.log
stopwaitsecs=60
stopsignal=sigint
minfds=10240
environment=SOKETI_SSL_CERT="/etc/letsencrypt/live/laraapp.com/fullchain.pem",SOKETI_SSL_KEY="/etc/letsencrypt/live/laraapp.com/privkey.pem", PATH="/home/Gabotron/.nvm/versions/node/v14.21.3/bin:%(ENV_PATH)s",NODE_ENV="production", 

Nginx 配置

server {
    server_name laraapp.com www.laraapp.com;

    root /var/www/laraapp.com/public;
    index index.php index.html;

    access_log /var/log/laraapp.com/access.log;
    error_log /var/log/laraapp.com/error.log;

    # serve static files directly
    location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
        access_log off;
        expires max;
        log_not_found off;
    }

    # removes trailing slashes (prevents SEO duplicate content issues)
    if (!-d $request_filename)
    {
        rewrite ^/(.+)/$ /$1 permanent;
    }

    # enforce NO www
    if ($host ~* ^www\.(.*))
    {
        set $host_without_www $1;
        rewrite ^/(.*)$ $scheme://$host_without_www/$1 permanent;
    }

    # unless the request is for a valid file (image, js, css, etc.), send to bootstrap
    if (!-e $request_filename)
    {
        rewrite ^/(.*)$ /index.php?/$1 last;
        break;
    }

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

    location ~* \.php$ {
        try_files $uri = 404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }

    location /ws/ {
        proxy_pass http://127.0.0.1:6001; # Point to the Soketi port
        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 $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/laraapp.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/laraapp.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
}

server {
    if ($host = www.laraapp.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    if ($host = laraapp.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    server_name laraapp.com www.laraapp.com;
    return 404; # managed by Certbot
}

前端连接日志

Pusher :  : ["Connecting",{"transport":"wss","url":"wss://laraapp.com:6001/app/9b9a4890c38f28f43777?protocol=7&client=js&version=7.0.6&flash=false"}]
 LOG  Pusher :  : ["State changed","connecting -> unavailable"]
 LOG  Pusher :  : ["Connecting",{"transport":"ws","url":"ws://laraapp.com:6001/app/9b9a4890c38f28f43777?protocol=7&client=js&version=7.0.6&flash=false"}]
 LOG  Pusher :  : ["Connecting",{"transport":"wss","url":"wss://laraapp.com:6001/app/9b9a4890c38f28f43777?protocol=7&client=js&version=7.0.6&flash=false"}]

Laravel 广播错误日志

[2024-01-11 17:27:21] production.ERROR: Pusher error: . {"exception":"[object] (Illuminate\\Broadcasting\\BroadcastException(code: 0): Pusher error: . at /Users/peter/Desktop/proyectos/laraapp.com/vendor/laravel/framework/src/Illuminate/Broadcasting/Broadcasters/PusherBroadcaster.php:128)

排查步骤

  1. 修复凭据不一致问题
    前端日志中的PUSHER_APP_KEY是9b9a4890c38f28f43777,但.env里的是9b9a489dffdf0c38f28f43777,两者缺失了dffdf部分,必须完全统一。更新React Native代码中的密钥,确保和Laravel.env一致。

  2. 调整前端连接方式(使用Nginx代理)
    Nginx已经配置了/ws/代理到Soketi,无需让前端直连6001端口(可能被防火墙拦截)。修改React Native的Echo配置:

    let options = {
        key: env.PUSHER_APP_KEY,
        wsHost: 'laraapp.com',
        wsPort: 443,
        wssPort: 443,
        path: '/ws', // 新增代理路径
        encrypted: true,
        forceTLS: true,
        enabledTransports: ['wss'],
    };
    

    这样前端通过443端口的Nginx代理连接Soketi,避免端口开放问题。

  3. 验证Soketi服务状态

    • 查看Soketi日志:cat /home/Gabotron/logs/soketi.err.log 和 cat /home/Gabotron/logs/soketi.out.log,确认服务是否正常启动,无SSL证书错误或端口占用。
    • 本地测试Soketi连接:使用wscat(需先安装npm install -g wscat)执行:
      wscat -c wss://127.0.0.1:6001/app/9b9a489dffdf0c38f28f43777?protocol=7&client=js&version=7.0.6
      
      若能成功连接并收到Pusher协议消息,说明Soketi服务正常。
  4. 检查防火墙规则

    • 若坚持直连6001端口,需在DigitalOcean控制面板的防火墙中添加入站规则,允许TCP 6001端口;同时在服务器上执行ufw allow 6001/tcp开放端口。
    • 若使用Nginx代理,只需确保443端口已开放(已由Certbot配置)。
  5. 优化Laravel日志获取详细错误

    • 在.env中设置LOG_LEVEL=debug,重新触发广播,查看storage/logs/laravel.log中的详细错误信息,定位Pusher连接失败的具体原因(如SSL验证、端口不通、密钥错误等)。
  6. 确认Soketi与Laravel的SSL配置匹配
    Supervisor中Soketi已配置SSL证书,所以Laravel的.env中PUSHER_SCHEME=https是正确的,但需确保Soketi监听的是6001端口的HTTPS,而非HTTP。可在Soketi启动命令中添加--port=6001 --ssl-cert=... --ssl-key=...(虽然环境变量已配置,但显式指定更保险)。

内容的提问来源于stack exchange,提问作者gabogabans

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 10:19:53