【问题标题】:Socket.io not disconnecting through Cloudflare/NginxSocket.io 未通过 Cloudflare/Nginx 断开连接
【发布时间】:2019-03-24 15:05:57
【问题描述】:

我有一个使用 Express.js 提供服务并使用 Socket.io 连接到后端的小型 Web 应用程序。为了公开,我使用 Nginx 作为反向代理,然后在最前面使用 Cloudflare。该应用程序依赖于在关闭或重新加载时触发disconnect 事件来跟踪在线用户等。通过 Nginx 和 Cloudflare 时,断开连接事件永远不会在后端触发。在本地开发时会这样做。

这是我的 Nginx 配置文件:

server {
    listen 80;
    server_name colab.gq;
    server_name www.colab.gq;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header X-Forwarded-For $remote_addr;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/colab.gq/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/colab.gq/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
}

这是我的服务器端代码的 sn-p:

io.on('connection', (socket) => {
  // Stuff here

  socket.on('disconnect', () => {
    console.log('disconnected!')
    // Stuff that relies on the disconnect event
  })
})

当用户关闭选项卡或重新加载页面时,断开连接事件应该触发,但在通过 Nginx 和 Cloudflare 传递连接时不会触发。提前感谢您的帮助!

更新:似乎在重新加载/关闭断开事件后几秒钟终于注册了。

【问题讨论】:

    标签: javascript node.js nginx socket.io cloudflare


    【解决方案1】:

    您必须像这样在 nginx 配置中将升级标头添加到您的套接字 io 路径,

        location ~* \.io {
          .. your configuration
    
          proxy_pass http://localhost:3000;
          proxy_redirect off;
    
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
        }
    

    由于您要求扩展答案,您可能已经知道的第一件事是 socket.io 是一个在底层使用 Websockets 协议的协议(所以两者都是相同的)。作为标准,Websockets 协议和 HTTP 协议都在同一个端口 80 或 443 上侦听。默认协议是 HTTP,如果用户想使用 websockets 协议,他/她必须发送从 HTTP 到 WS 协议的升级请求,并且有一些关键身份验证和步骤。

    这就是为什么你需要将它们放在你的 nginx 配置中。

    如果您需要更多关于h协议升级机制的信息,请参考this

    尽管在我看来,这不是 this 问题的完全重复,但我觉得有义务感谢 @Paulo 提供完美的答案,即使不被接受。

    【讨论】:

    • 我很好奇,HostX-NginX-Proxy 做什么?
    • 对不起,我编辑了我的答案,升级标题在你的情况下就足够了
    • 啊,好的。记下您的编辑。介意解释一下升级的作用吗?仍然会接受你的回答,但我很感兴趣。
    • 需要http版本
    【解决方案2】:

    可能发生的是两件事。

    第一个:Socket.io 有很长的超时时间(因此有几秒钟),并且在声明它已断开连接之前正在寻找重新连接。检查 reconnect_attempt 或 reconnecting 事件(注意我有一段时间没有使用 socket.io,所以我可能在时间上错了)

    第二个:你没有告诉 socket.io 它在关闭浏览器窗口时断开连接。

    我建议向您的 javascript 添加一个事件侦听器,它会告诉您的服务器在窗口关闭时它正在断开连接。

        window.addEventListener('beforeunload', () => {
           socket.disconnect();
        }
    

    【讨论】:

    • 谢谢,但请参阅 JKK 的回答。这对我有用,我已经尝试过类似于你推荐的方法。
    • 太棒了,很高兴你得到它。
    猜你喜欢
    • 1970-01-01
    • 2012-08-16
    • 1970-01-01
    • 2017-08-18
    • 2022-06-30
    • 1970-01-01
    • 2014-01-13
    • 2017-05-25
    相关资源
    最近更新 更多