node_redis :2.7.1
redis :3.2
プラットフォーム:Amazon linux
説明:
redisのスナップショットが発生すると、redisクライアントが切断されます。 クライアントは再接続して再サブスクライブしますが、データを受信しなくなります。 これは、redis-cliを介してSAVE
コマンドを発行することで再現できます。
JS
const redis = require('redis');
const redisClient = redis.createClient({
host: config.redisEndpoint,
port: config.redisPort,
});
redisClient.on('connect', () => {
console.log('Connected to Redis');
console.log('subscription_set:', redisClient.subscription_set);
});
redisClient.on('reconnecting', (stats) => {
console.log('Reconnecting to Redis', stats);
});
redisClient.on('error', (error) => {
console.log('Failed to connect to Redis: ', error);
});
redisClient.on('subscribe', (channel, count) => { // eslint-disable-line no-unused-vars
console.log('Subscribed to: ', channel, count);
});
redisClient.on('message', (channel, message) => { // eslint-disable-line no-unused-vars
console.log('Received from: ', channel, message);
});
redisClient.subscribe('test');
ログ
初期接続
info: Connected to Redis
info: subscription_set:
info: Subscribed to: test 1
redis-cliでSAVEコマンドを発行する
info: Error: Redis connection to 34.213.3.19:6379 failed - read ECONNRESET
info: Reconnecting to Redis delay=983, attempt=4, code=ECONNRESET, errno=ECONNRESET, syscall=connect, address=127.0.0.1, port=6379, total_retry_time=1118, times_connected=1
info: Connected to Redis
info: subscription_set: subscribe_test=test
info: Subscribed to: test 1
この時点で、クライアントはチャネルテストに公開されたデータを受信しなくなります。 ご不明な点がある場合、または再現するための詳細情報が必要な場合は、お知らせください。
@BridgeAR @ iamjem #1249に関連している可能性があります
詳細な説明ありがとうございますが、まだ再現できていません。 redis-cliを介してSAVE
を発行すると、接続がリセットされません。
redisサーバーを手動で停止して再起動すると、メッセージを正常に受信しているようです。
私はこれをMacでテストしてきましたが、Linuxでも再現しようとします
うーん...それは面白いです。 これは、ソースから構築された完全にストックされたredisインストールで発生していました。 私が変更した唯一のオプションは、リモート接続を許可することでした。 すぐに見て、何が起きているのか理解できるかどうかを確認します。 @jdegger
@jdeggerローカルで再現することはできません
さて、ようやく確実に再現できました。 いくつかの要件があります。
tcp-keepalive 0
表示されるのは、2時間ごと(少なくとも私にとっては)がECONNRESETエラーであるということです。 この時点で、ソケットはまだredisで開いているように見えますが、ノードプロセスがそのソケットへの参照を失い、新しいソケットを開いた可能性がありますか? 一晩、redis-cliからCLIENT LIST
を発行するときに、2時間のブロックごとに1つのクライアントが接続され、さらに現在実行中のプロセスがありました。
クライアントはすべて正常に再接続しましたが、データを受信していなかったことに注意することが重要です。 データがプッシュされているという予感がありますが、古い接続では新しい接続ではありません...しかし、それは完全に予感です。
さて、これがnode_redisのバグなのか、実際にはnodeのバグなのか、100%わからないので、これが間違ったファイルの場所である場合は、私に知らせてください。 試してデバッグ/ステップスルーできれば幸いですが、時間は限られています。
修正は、接続をアクティブに保つtcp-keepalive 300
を設定することでした...しかし、クライアントは正常に再接続できるはずなので、これは不安定に感じます。
@shmendo
また、ECONNRESETエラーが2時間ごとに発生することも示しています。 しかし、私はtcp-keepaliveをチェックしました、それは300です
CONFIG GET tcp-keepalive
1) "tcp-keepalive"
2) "300"
最も参考になるコメント
さて、ようやく確実に再現できました。 いくつかの要件があります。
tcp-keepalive 0
表示されるのは、2時間ごと(少なくとも私にとっては)がECONNRESETエラーであるということです。 この時点で、ソケットはまだredisで開いているように見えますが、ノードプロセスがそのソケットへの参照を失い、新しいソケットを開いた可能性がありますか? 一晩、redis-cliから
CLIENT LIST
を発行するときに、2時間のブロックごとに1つのクライアントが接続され、さらに現在実行中のプロセスがありました。クライアントはすべて正常に再接続しましたが、データを受信していなかったことに注意することが重要です。 データがプッシュされているという予感がありますが、古い接続では新しい接続ではありません...しかし、それは完全に予感です。
さて、これがnode_redisのバグなのか、実際にはnodeのバグなのか、100%わからないので、これが間違ったファイルの場所である場合は、私に知らせてください。 試してデバッグ/ステップスルーできれば幸いですが、時間は限られています。
修正は、接続をアクティブに保つ
tcp-keepalive 300
を設定することでした...しかし、クライアントは正常に再接続できるはずなので、これは不安定に感じます。