Socket.io 未通过 Cloudflare/Nginx 断开连接
Socket.io not disconnecting through Cloudflare/Nginx
我有一个使用 Express.js 提供服务并使用 Socket.io 连接到后端的小型网络应用程序。为了做到 public,我使用 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
}
这是我的服务器端代码片段:
io.on('connection', (socket) => {
// Stuff here
socket.on('disconnect', () => {
console.log('disconnected!')
// Stuff that relies on the disconnect event
})
})
当用户关闭选项卡或重新加载页面时,应该触发断开连接事件,但在通过 Nginx 和 Cloudflare 传递连接时它永远不会触发。在此先感谢您的帮助!
更新:似乎在 reloading/closing 断开连接事件终于注册后几秒钟。
你必须像这样在 nginx 配置中添加升级 headers 到你的套接字 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 协议 he/she 必须发送从 HTTP 到 WS 协议的升级请求并且有一些关键的身份验证和步骤。
这就是为什么您需要将它们放入您的 nginx 配置中。
如果您需要有关协议升级机制的更多信息,请参阅this。
尽管在我看来,这并不是 this question, I feel obligated to give credits for @Paulo 提供完美答案的完全重复,即使不被接受。
可能发生的是两件事。
1st:Socket.io 超时时间很长(因此有几秒钟)并且在声明已断开连接之前希望重新连接。检查 reconnect_attempt 或重新连接事件(请注意,我已经有一段时间没有使用 socket.io,所以我在这方面的时间可能是错误的)
第二:您没有告诉 socket.io 它在关闭浏览器后断开连接 window。
我建议向您的 javascript 添加一个事件侦听器,它会告诉您的服务器它在 window 关闭时断开连接。
window.addEventListener('beforeunload', () => {
socket.disconnect();
}
我有一个使用 Express.js 提供服务并使用 Socket.io 连接到后端的小型网络应用程序。为了做到 public,我使用 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
}
这是我的服务器端代码片段:
io.on('connection', (socket) => {
// Stuff here
socket.on('disconnect', () => {
console.log('disconnected!')
// Stuff that relies on the disconnect event
})
})
当用户关闭选项卡或重新加载页面时,应该触发断开连接事件,但在通过 Nginx 和 Cloudflare 传递连接时它永远不会触发。在此先感谢您的帮助!
更新:似乎在 reloading/closing 断开连接事件终于注册后几秒钟。
你必须像这样在 nginx 配置中添加升级 headers 到你的套接字 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 协议 he/she 必须发送从 HTTP 到 WS 协议的升级请求并且有一些关键的身份验证和步骤。
这就是为什么您需要将它们放入您的 nginx 配置中。
如果您需要有关协议升级机制的更多信息,请参阅this。
尽管在我看来,这并不是 this question, I feel obligated to give credits for @Paulo 提供完美答案的完全重复,即使不被接受。
可能发生的是两件事。
1st:Socket.io 超时时间很长(因此有几秒钟)并且在声明已断开连接之前希望重新连接。检查 reconnect_attempt 或重新连接事件(请注意,我已经有一段时间没有使用 socket.io,所以我在这方面的时间可能是错误的)
第二:您没有告诉 socket.io 它在关闭浏览器后断开连接 window。
我建议向您的 javascript 添加一个事件侦听器,它会告诉您的服务器它在 window 关闭时断开连接。
window.addEventListener('beforeunload', () => {
socket.disconnect();
}