easyswoole 改用redis做session,高并发下报错的解决方法

按照官方的写法:在mainServerCreate里面初始化,将Hander带进去

$handler = new \EasySwoole\Session\SessionRedisHandler(
    \EasySwoole\RedisPool\Redis::defer('redis')
    ,$sessionData['maxLifeTime']
);
Session::getInstance($handler,$sessionData['session_name'],'php_session_dir');

 

但是你会遇到1一个问题,服务没有办法启动。因此我把上面的代码放到onRequest里面。可以启动。整个使用没有啥问题。但是你通过ab等工具做高并发。会报错

2020-07-21 17:50:04][debug][error]:[Uncaught Swoole\Error: Socket#35 has already been bound to another coroutine#15684, reading of the same socket in coroutine#15685 at the same time is not allowed in /home/kenny/KennyPrograms/test_main/vendor/easyswoole/redis/src/Client.php:65
Stack trace:
#0 /home/kenny/KennyPrograms/test_main/vendor/easyswoole/redis/src/Client.php(65): Swoole\Coroutine\Client->recv()
#1 /home/kenny/KennyPrograms/test_main/vendor/easyswoole/redis/src/Redis.php(2908): EasySwoole\Redis\Client->recv()
#2 /home/kenny/KennyPrograms/test_main/vendor/easyswoole/redis/src/Redis.php(607): EasySwoole\Redis\Redis->recv()
#3 /home/kenny/KennyPrograms/test_main/Commons/PackageRewrite/SessionRedisHandler.php(54): EasySwoole\Redis\Redis->get()
#4 /home/kenny/KennyPrograms/test_main/vendor/easyswoole/session/src/Session.php(151): EasySwoole\Session\SessionRedisHandler->read()
#5 /home/kenny/KennyPrograms/test_main/vendor/easyswoole/session/src/Session.php(93): EasySwoole\Session\Session->start()
#6 /home/kenny/KennyPrograms/oko at file:/home/kenny/KennyPrograms/test_main/vendor/easyswoole/redis/src/Client.php line:65]

原因:has already been bound to another coroutine#15684, reading of the same socket in coroutine#15685 at the same time is not allowed in 

协程出了问题了。后来排查发现是hander出的问题。也就是不能再SessionRedisHandler 使用你传进去的hander。

必须从全局中去获取redis连接处。

当然同时也解决了mainServerCreate报错问题,一举两得。

附上源码:

redis=$redis;
        $this->maxLifeTime=$maxLifeTime;

    }

    public function close()
    {
        return true;
    }

    public function destroy($session_id)
    {
        //return $this->redis->hDel($this->name,$session_id);
        //return $this->redis->del($this->name.':'.$session_id);
        return Redis::defer('redis')->del($this->name.':'.$session_id);
    }

    public function gc($maxlifetime)
    {
        /*
         * redis no need  use it
         */
    }

    public function open($save_path, $name)
    {
        $this->savePath = $save_path;
        $this->name = $name;
        return true;
    }

    public function read($session_id)
    {
        //return $this->redis->hGet($this->name,$session_id);

        //return $this->redis->get($this->name.':'.$session_id);
        return Redis::defer('redis')->get($this->name.':'.$session_id);
    }

    public function write($session_id, $session_data)
    {

        //return $this->redis->hSet($this->name,$session_id,$session_data);
        //return $this->redis->set($this->name.':'.$session_id,$session_data,$this->maxLifeTime);
        return Redis::defer('redis')->set($this->name.':'.$session_id,$session_data,$this->maxLifeTime);
    }
}

 

你可能感兴趣的:(easyswoole 改用redis做session,高并发下报错的解决方法)