在app/bootstrap文件夹下新增一个RedisLogBootstrap.php
<?php
namespace app\bootstrap;
use Webman\Bootstrap;
use support\Redis;
use Illuminate\Redis\Events\CommandExecuted;
use app\tools\Log;
class RedisLogBootstrap implements Bootstrap
{
public static function start($worker)
{
// Is it console environment ?
$is_console = !$worker;
if ($is_console) {
return;
}
if( $worker ->name == 'monitor' || $worker ->name == 'cron' ){
return;
}
$readCommand = [ 'info', 'dbsize', 'exists', 'type', 'ttl', 'pttl', 'keys', 'scan', 'sscan', 'hscan', 'zscan' ];
$redisLogType = env( 'REDIS_LOG_TYPE', 0 ); // 1记录所有redis操作 2:记录所有写操作 0:不记录redis日志
if ( $redisLogType == 0 ) return;
foreach ( Redis::instance()->connections() ?: [] as $connection) {
/** @var \Illuminate\Redis\Connections\Connection $connection */
$name = $connection->getName();
echo $worker ->name.' ddd '.$name.PHP_EOL;
echo $worker ->name.' '.$name .' redis hash:'.spl_object_hash($connection).PHP_EOL;
$connection->listen( function( CommandExecuted $command ) use( $readCommand, $redisLogType ) {
echo $command ->command.PHP_EOL;
if( $redisLogType == 2 && in_array( strtolower( $command ->command ), $readCommand ) ){
return;
}
foreach ($command->parameters as &$item) {
if (is_array($item)) {
$item = implode('\', \'', $item);
}
}
if( implode( ' ', $command ->parameters ) == 'PING' ) return;
$log = sprintf( '%s %s [%sms]', $command ->command, implode( ' ', $command ->parameters ), $command ->time, PHP_EOL );
Log::channel( 'redis' ) ->info( $log );//redis操作日志
if( env( 'IS_DEBUG' ) ){
echo $log.PHP_EOL;
}
});
}
}
}
webman会启动一个http进程,2个长连接进程,发现长连接进程里,无法捕获到redis命令,http连接里可以。最后发现bootstrap里的redis connection hash值与 长连接进程业务代码里的 redis connection hash 不一样。这是为什么?
说明长连接进程没执行redis操作。posix_getpid() 能获取到进程pid,bootstrap和执行redis的地方打印下posix_getpid() 就知道长连接进程是否执行了redis操作。
不同进程里connection对象不是同一个对象,进程间是隔离的,不是同一个对象,对象hash不通很正常啊。
长连接进行了redis操作。我打印了进程id,是同一个进程,在bootstrap里对象hash和业务代码里对象hash不一样
bootstrap里遍历 Redis::instance()->connections() 可能有问题,这时候还没创建对应的redis连接,redis连接应该是使用时才创建的。
也不是,我在另外一个启动脚本里,所有的进程都做了一些其他操作,涉及到redis操作的。而且我在bootstrap里打印了,redis connection 是有的,而且name也是对的
在业务代码里,操作redis后遍历 Redis::instance()->connections() 看下是否对应上,业务代码里操作redis的时候可能是新建的连接。
大佬能帮忙看看吗,业务代码就是用的webman的redis