Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

when keepAlive parameter is set, the TCP keep-alive is enabled but the specified timeout is not applied #1339

Closed
ArnoldZokas opened this issue Apr 21, 2021 · 2 comments · Fixed by #1554

Comments

@ArnoldZokas
Copy link

ioredis version: 4.26.0
Node.js version: 14.16.1
OS: Ubuntu 18.04.3 LTS

Setting the keepAlive option enables the TCP keep-alive mechanism but does not apply the specified timeout.

This can be reproduced with:

const Redis = require("ioredis");

const redis = new Redis({
  host: 'localhost',
  keepAlive: 30000, // should set socket option TCP_KEEPIDLE=30
});

redis.on('connect', () => {
  console.log('Connected!');
});

Running knetstat to inspect socket options shows the socket was created with TCP_KEEPIDLE=60 (which is the Node.js default):

$ cat /proc/net/tcpstat
Recv-Q Send-Q Local Address   Foreign Address  Stat Diag Options
     0      0 127.0.0.1:40792 127.0.0.1:6379   ESTB      SO_REUSEADDR=0,SO_REUSEPORT=0,SO_KEEPALIVE=1,TCP_KEEPIDLE=60,TCP_KEEPCNT=10,TCP_KEEPINTVL=1,TCP_NODELAY=1,TCP_DEFER_ACCEPT=0

This is likely due to socket.setKeepAlive() being called after the connection has been established.
To test this I have created a socket and tried calling socket.setKeepAlive() before and after calling socket.connect().

When socket.setKeepAlive() is called before socket.connect():

const net = require('net');

const socket = new net.Socket();

socket.setKeepAlive(true, 10000);

socket.connect({
  host: 'localhost',
  port: 6379,
});

socket.on('connect', () => {
  console.log('Connected!');
});

knetstat reports TCP_KEEPIDLE=10 - keep-alive is enabled and the correct timeout is applied


When socket.setKeepAlive() is called after socket.connect():

const net = require('net');

const socket = new net.Socket();

socket.connect({
  host: 'localhost',
  port: 6379,
});

socket.setKeepAlive(true, 10000);

socket.on('connect', () => {
  console.log('Connected!');
});

knetstat reports TCP_KEEPIDLE=60 - keep-alive is enabled but the Node.js default timeout is applied

@marcbachmann
Copy link
Collaborator

Thanks for the investigation. I think the cause of that issue is nodejs/node#31663

github-actions bot pushed a commit that referenced this issue Mar 31, 2022
## [5.0.3](v5.0.2...v5.0.3) (2022-03-31)

### Bug Fixes

* add named exports to keep compatible with @types/ioredis ([#1552](#1552)) ([a89a900](a89a900))
* Fix failover detector with sentinel and tls streams ([ac00a00](ac00a00))
* handle NOPERM error for monitor ([93b873d](93b873d)), closes [#1498](#1498)
* Hook up the keepAlive after a successful connect ([14f03a4](14f03a4)), closes [#1339](#1339)
@github-actions
Copy link

🎉 This issue has been resolved in version 5.0.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

janus-dev87 added a commit to janus-dev87/ioredis-work that referenced this issue Mar 1, 2024
## [5.0.3](redis/ioredis@v5.0.2...v5.0.3) (2022-03-31)

### Bug Fixes

* add named exports to keep compatible with @types/ioredis ([#1552](redis/ioredis#1552)) ([a89a900](redis/ioredis@a89a900))
* Fix failover detector with sentinel and tls streams ([ac00a00](redis/ioredis@ac00a00))
* handle NOPERM error for monitor ([93b873d](redis/ioredis@93b873d)), closes [#1498](redis/ioredis#1498)
* Hook up the keepAlive after a successful connect ([14f03a4](redis/ioredis@14f03a4)), closes [#1339](redis/ioredis#1339)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants