node.js + socket.io 에서 일정시간 이후 socket closed 되는 문제

2021. 8. 10. 01:45개발/Node.js

반응형

node.js 서버에서 child process로 python script를 돌리고, 그 결과를 socket.io 를 통해 출력하는 동안 문제가 발생했다.

 

child process 에서 발생하는 출력이 있을때마다 socket.io 를 통해 front쪽으로 전송해주었었는데, child process의 load시간이 걸리면, 일정시간동안 출력할 것이 없어 socket이 자동으로 closed 된다.

(socket.io 에서는 client <-> server 간 통신이 일정 시간 동안 없으면 closed 된다고 한다.)

 

stackoverflow를 조금 찾아보면 setInterval 함수를 이용해 수십초에 한번 연결을 확인하는 ping을 날려서 특정시간동안 통신을 안하는 상황 자체를 만들지 않는 방법이 있었다. single thread를 사용하는 node.js 의 특성상 child process에 load가 걸리면 setInterval를 1초로 설정했었더라도 Interval이 10초이상 간격이 벌어지는 경우가 발생했다. 이 문제를 코드로 해결할 수 있지만, 더 간단하게 socket.io 설정만 바꿔도 충분히 해결할 수 있었다.

 

socket.io 공홈을 찾아보면 아래와같은 옵션을 제공해주고 있다.

 

new Server(httpServer[, options])

  • httpServer (http.Server) the server to bind to.
  • options (Object)
const io = require("socket.io")();
// or
const { Server } = require("socket.io");
const io = new Server();

 

Available options:

OptionDefault valueDescription

path /socket.io name of the path to capture
serveClient true whether to serve the client files
adapter - the adapter to use. Defaults to an instance of the Adapter that ships with socket.io which is memory based. See socket.io-adapter
parser - the parser to use. Defaults to an instance of the Parser that ships with socket.io. See socket.io-parser.
connectTimeout 45000 the number of ms before closing a client that has not successfully joined a namespace.

Available options for the underlying Engine.IO server:

OptionDefault valueDescription

pingTimeout 5000 how many ms without a pong packet to consider the connection closed
pingInterval 25000 how many ms before sending a new ping packet
upgradeTimeout 10000 how many ms before an uncompleted transport upgrade is cancelled
maxHttpBufferSize 1e6 how many bytes or characters a message can be, before closing the session (to avoid DoS).
allowRequest   A function that receives a given handshake or upgrade request as its first parameter, and can decide whether to continue or not. The second argument is a function that needs to be called with the decided information: fn(err, success), where success is a boolean value where false means that the request is rejected, and err is an error code.
transports ["polling", "websocket"] transports to allow connections to
allowUpgrades true whether to allow transport upgrades
perMessageDeflate false parameters of the WebSocket permessage-deflate extension (see ws module api docs). Set to true to enable.
httpCompression true parameters of the http compression for the polling transports (see zlib api docs). Set to false to disable.
wsEngine ws what WebSocket server implementation to use. Specified module must conform to the ws interface (see ws module api docs). Default value is ws. An alternative c++ addon is also available by installing the eiows module.
cors   the list of options that will be forwarded to the cors module
cookie   the list of options that will be forwarded to the cookie module
allowEIO3 false whether to enable compatibility with Socket.IO v2 clients

 

 

 

pingTimeout : Default value는 5000ms 로 connection closed로 인지하는 timeout 시간을 뜻한다. 이 값을 크게 하면 그 시간동안 데이터 전송이 없어도 connection closed 라고 판단하지 않는다.

 

pingInterval : Default value는 25000ms 로 connection이 유지 되고 있는지 확인하는 주기를 뜻한다.

 

Default 설정값을 토대로 해석해보면

pingInterval 에 한번씩 ping을 보내서 pingTimeout 안에 응답이 오면 connection이 유지 된다고 판단한다.

 

 

Project 의 방향에 맞게 위 두개의 값 중 한개를 높여주면 해결할 수 있다.

 

사용 예시

const io = require("socket.io")(3000, {
  // below are engine.IO options
  pingInterval: 10000,
  pingTimeout: 5000
});

 

 

 

반응형