phpredis subscribeタイムアウト問題と解決
5684 ワード
問題の説明
redisはpub/sub機能を提供していますが、phpredisのsubscribeを使用すると、次のような問題が見つかりました(sub.php).
コードが実行されると、demoチャンネルからのメッセージが一定期間受信されていない場合、次のエラーが表示されます.
原因分析
理由を調べるためにstraceを使用してコードを追跡しました.
切り取り部分の重要な出力は次のとおりです.
エラーの本質はpoll設定受信タイムアウトによるものであり,starceの結果からこのタイムアウトのデフォルトは60 sであることが分かった.
解決する
タイムアウトを変更する方法は2つあります.方法1はコードの先頭で設定します.メソッド2 redis connect後に を実行
どちらの方法の-1もタイムアウトしないことを示し、タイムアウトを自分の希望する時間に設定することもできます.いずれの方法を使用しても、再びstraceを使用すると、pollのタイムアウトが-1に設定されていることがわかります.
個人的におすすめの方法2は、redis自体にのみ影響します.メソッド1は、file_などの他のメソッドに影響を与えます.get_contentsなど.
まとめ
phpredisのsubscribeを使用すると、デフォルト60でメッセージが受信されず、sub側はタイムアウト異常で終了します.タイムアウト時間を延長するか、タイムアウトしないかを自分で設定できます.
redisはpub/sub機能を提供していますが、phpredisのsubscribeを使用すると、次のような問題が見つかりました(sub.php).
/* demo , */
function process($redis, $chan, $msg){
var_dump($msg);
}
$redis = new Redis();
$res = $redis->connect('127.0.0.1', '7979');
$redis->subscribe(array('demo'), 'process');
コードが実行されると、demoチャンネルからのメッセージが一定期間受信されていない場合、次のエラーが表示されます.
PHP Fatal error: Uncaught exception 'RedisException' with message 'read error on connection' in sub.php:11
Stack trace:
#0 /search/ballqiu/sub.php(11): Redis->subscribe(Array, 'process')
#1 {main}
thrown in sub.php on line 11
原因分析
理由を調べるためにstraceを使用してコードを追跡しました.
strace php sub.php
切り取り部分の重要な出力は次のとおりです.
// redis
connect(3, {sa_family=AF_INET, sin_port=htons(7979), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
// subscribe
sendto(3, "subscribe demo\r
", 17, MSG_DONTWAIT, NULL, 0) = 17
//
recvfrom(3, "*3\r
$9\r
subscribe\r
$4\r
demo\r
:1\r"..., 8192, MSG_DONTWAIT, NULL, NULL) = 33
poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)
// 60s
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 0 (Timeout)
// ,
close(3) = 0
//
write(2, "PHP Fatal error: Uncaught excep"..., 261PHP Fatal error: Uncaught exception 'RedisException' with message 'read error on connection'
エラーの本質はpoll設定受信タイムアウトによるものであり,starceの結果からこのタイムアウトのデフォルトは60 sであることが分かった.
解決する
タイムアウトを変更する方法は2つあります.方法1はコードの先頭で設定します.
ini_set('default_socket_timeout', -1);
$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);
どちらの方法の-1もタイムアウトしないことを示し、タイムアウトを自分の希望する時間に設定することもできます.いずれの方法を使用しても、再びstraceを使用すると、pollのタイムアウトが-1に設定されていることがわかります.
recvfrom(3, "*3\r
$9\r
subscribe\r
$4\r
demo\r
:1\r"..., 8192, 0, NULL, NULL) = 33
poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)
// -1,
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, -1
個人的におすすめの方法2は、redis自体にのみ影響します.メソッド1は、file_などの他のメソッドに影響を与えます.get_contentsなど.
まとめ
phpredisのsubscribeを使用すると、デフォルト60でメッセージが受信されず、sub側はタイムアウト異常で終了します.タイムアウト時間を延長するか、タイムアウトしないかを自分で設定できます.