I'm currently working on a project with socket.io, express and redis. Below is the minimal reproducible code. We use node@14.16.0, express@4.17.1, ioredis@4.19.4, socket.io@3.1.0
import { Server, Socket } from 'socket.io';
import IORedis from 'ioredis';
import * as http from 'http';
import express from 'express';
const app = express();
const httpServer = http.createServer(app);
httpServer.on('clientError', (err: any, socket: any) => {
if (err.code === 'ECONNRESET' || !socket?.writable) {
Logger.warn(`httpServer clientError: `, err);
return;
}
});
httpServer.listen(80, () => console.log("The server is running"));
const io = new Server(httpServer, {
pingTimeout: 60000,
parser: customParser,
});
io.on('error', (e: any) => {
Logger.error('io error', e);
});
io.on('connection', (socket: Socket) => {
socket.on('disconnect', (reason: any) => {
});
socket.on('error', (e: any) => {
Logger.error(`socket ${socket.id} error`, e);
});
});
const redis = new IORedis(redisOptions);
redis.on('connect', () => {});
redis.on('error', () => {});
process.on("uncaughtException", (e: any) => console.log(e))
The service works well, but from time to time, it will throw an Error: read ECONNRESET at TCP.onStreamRead (internal/stream_base_commons.js)
I did a research on stackoverflow, there are three types of causes or solutions of the problem.
- Redis will close its connection if the connection is inactive for too long, however we will update Redis for an interval of 5s
- Using pm2 will handle uncaught errors, but indeed we use pm2 on our linux servers, but every time this error ocuurs, the service will be restarted which we don't want
- Use
domainmodule in nodedejs, but it has been deprecated for a long time
I just can't figure out why this error can sneak out after I put so many error handlers even process.on("uncaughtException"),
and the error message is so poor, with which we cannot detect where is wrong