webman安装gatewayworker后,无法监听到bussiness的redis执行命令事件

pengzhen

在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 不一样。这是为什么?

75 2 0
2个回答

damao

说明长连接进程没执行redis操作。posix_getpid() 能获取到进程pid,bootstrap和执行redis的地方打印下posix_getpid() 就知道长连接进程是否执行了redis操作。

不同进程里connection对象不是同一个对象,进程间是隔离的,不是同一个对象,对象hash不通很正常啊。

  • pengzhen 1天前

    长连接进行了redis操作。我打印了进程id,是同一个进程,在bootstrap里对象hash和业务代码里对象hash不一样

  • damao 1天前

    bootstrap里遍历 Redis::instance()->connections() 可能有问题,这时候还没创建对应的redis连接,redis连接应该是使用时才创建的。

  • pengzhen 1天前

    也不是,我在另外一个启动脚本里,所有的进程都做了一些其他操作,涉及到redis操作的。而且我在bootstrap里打印了,redis connection 是有的,而且name也是对的

  • damao 1天前

    在业务代码里,操作redis后遍历 Redis::instance()->connections() 看下是否对应上,业务代码里操作redis的时候可能是新建的连接。

pengzhen

大佬能帮忙看看吗,业务代码就是用的webman的redis

  • 暂无评论
🔝