Node-redis: 再接続後、サブスクリプションはデータを受信しません

作成日 2017年07月05日  ·  6コメント  ·  ソース: NodeRedis/node-redis

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

この時点で、クライアントはチャネルテストに公開されたデータを受信しなくなります。 ご不明な点がある場合、または再現するための詳細情報が必要な場合は、お知らせください。

bug

最も参考になるコメント

さて、ようやく確実に再現できました。 いくつかの要件があります。

  • redis 3.2.0- tcp-keepalive 0
  • チャネルを設定する
  • 接続するノードスクリプトを構成し、チャネルにサブスクライブします
  • 2時間1分待つ

表示されるのは、2時間ごと(少なくとも私にとっては)がECONNRESETエラーであるということです。 この時点で、ソケットはまだredisで開いているように見えますが、ノードプロセスがそのソケットへの参照を失い、新しいソケットを開いた可能性がありますか? 一晩、redis-cliからCLIENT LISTを発行するときに、2時間のブロックごとに1つのクライアントが接続され、さらに現在実行中のプロセスがありました。

クライアントはすべて正常に再接続しましたが、データを受信して​​いなかったことに注意することが重要です。 データがプッシュされているという予感がありますが、古い接続では新しい接続ではありません...しかし、それは完全に予感です。

さて、これがnode_redisのバグなのか、実際にはnodeのバグなのか、100%わからないので、これが間違ったファイルの場所である場合は、私に知らせてください。 試してデバッグ/ステップスルーできれば幸いですが、時間は限られています。

修正は、接続をアクティブに保つtcp-keepalive 300を設定することでした...しかし、クライアントは正常に再接続できるはずなので、これは不安定に感じます。

全てのコメント6件

@BridgeAR @ iamjem #1249に関連している可能性があります

詳細な説明ありがとうございますが、まだ再現できていません。 redis-cliを介してSAVEを発行すると、接続がリセットされません。

redisサーバーを手動で停止して再起動すると、メッセージを正常に受信しているようです。

私はこれをMacでテストしてきましたが、Linuxでも再現しようとします

うーん...それは面白いです。 これは、ソースから構築された完全にストックされたredisインストールで発生していました。 私が変更した唯一のオプションは、リモート接続を許可することでした。 すぐに見て、何が起きているのか理解できるかどうかを確認します。 @jdegger

@jdeggerローカルで再現することはできません

さて、ようやく確実に再現できました。 いくつかの要件があります。

  • redis 3.2.0- tcp-keepalive 0
  • チャネルを設定する
  • 接続するノードスクリプトを構成し、チャネルにサブスクライブします
  • 2時間1分待つ

表示されるのは、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"
このページは役に立ちましたか?
0 / 5 - 0 評価