-
Notifications
You must be signed in to change notification settings - Fork 10.1k
Description
Describe the bug
We use socket.io with Google Cloud Run with with redis-adapter for exchanging data across node-cluster and multiple containers. The challenge is that Google Cloud Run kills the connections every 60min, we don't use sticky extension as we work on websockets only ourselves. Thus do not support polling. When scaling the containers no matter in which direction, it happens from time to time that the client gets a socket connection, but from server the event "connection" is not called. As a result, all other events on the socket itself do not work.
Important: We use Namespaces and Channels
To Reproduce
- create a system with multiple servers and node-cluster
- use redis-adapter for exchange between all nodes
- just connect with the clients, simulate disconnects, or wait for normal disconnect from server (tcp)
- sometimes it works sometimes not, connection will not fired
Version for frontend and backend:
"@socket.io/admin-ui": "^0.5.1",
"@socket.io/redis-adapter": "^8.1.0",
"redis": "^4.6.5",
"socket.io": "^4.6.1",
"socket.io-client": "^4.6.1",
Redis Server 6.x+ (issue also with redis server 4.x+)
Server
Code Example
import { Server } from "socket.io";
/* ... */
// initialize socket io
const io = new Server(app.http, {
noServer: true,
cors: {
origin: "*",
methods: ["GET", "POST"],
credentials: true
}
});
const redisPub = activeRedisClient.duplicate();
await redisPub.connect();
await redisPub.ping();
const redisSub = activeRedisClient.duplicate();
await redisSub.connect();
await redisSub.ping();
io.adapter(createAdapter(redisPub, redisSub, {
requestsTimeout: 3000
}));
const dynamicNamespace = io.of(async (name, auth, next) => {
next(null, true);
});
dynamicNamespace.use(async (socket, next) => { next(null); });
dynamicNamespace.on('connection', async (socket) => {
// this event sometimes not called
socket.on('disconnect', async () => {
// this event sometimes not added / called
});
socket.on('message', async () => {
// this event sometimes not added / called
});
});
Client
import { io } from "socket.io-client";
const socket = io("ws://localhost:3000/", {
transports: ['websocket'],
auth: {
token: 'jwt-token',
},
});
socket.on("connect", () => {
console.log(`connect ${socket.id}`);
});
socket.on("disconnect", () => {
console.log("disconnect");
});
Expected behavior
It is expected that the event "connection" is always called on the server. But this is not the case, so the clients can do what they want, they can not dive into the normal program landscape. However, the socket connection remains. So there is a socket connection without the event "connection" being called on the server.
Platform:
- Device: PC, Notebook, Mac
- OS: Windows, Linux, OSX
- Browser: Safari (newest), Chrome (newest), Firefox (newest)
Additional context
Important, socket.io server running in google cloud run (docker container) and scale up/down up to the traffic, we had 250 connection at one container, a scale will happen at 150 open request.