🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 在多个协程间共用同一个协程客户端 同步阻塞程序不同,协程是并发处理请求的,因此同一时间可能会有很多个请求在并行处理,一旦共用客户端连接,就会导致不同协程之间发生数据错乱。 #### 错误的代码 ```php $server = new Swoole\Http\Server('127.0.0.1', 9501); $server->on('Receive', function ($serv, $fd, $rid, $data) { $redis = RedisFactory::getRedis(); $result = $redis->hgetall('key'); $resp->end(var_export($result, true)); }); $server->start(); class RedisFactory { private static $_redis = null; public static function getRedis() { if (null === self::$_redis) { $redis = new \Swoole\Coroutine\Redis(); $redis->connect('127.0.0.1', 6379); self::$_redis = $redis; } return self::$_redis; } } ``` #### 正确的代码 基于`SplQueue`实现协程客户端的连接池,可以复用协程客户端,实现长连接。 ```php $pool = new RedisPool(); $server = new Swoole\Http\Server('127.0.0.1', 9501); $server->on('Request', function($req, $resp) use ($pool) { //从连接池中获取一个Redis协程客户端 $redis = $pool->get(); //连接失败 if ($redis === false) { $resp->end("ERROR"); return; } $result = $redis->hgetall('key'); $resp->end(var_export($result, true)); //释放客户端,其他协程可复用此对象 $pool->put($redis); }); $server->start(); class RedisPool { protected $pool; function __construct() { $this->pool = new SplQueue; } function put($redis) { $this->pool->push($redis); } function get() { //有空闲连接 if (count($this->pool) > 0) { return $this->pool->pop(); } //无空闲连接,创建新连接 $redis = new Swoole\Coroutine\Redis(); $res = $redis->connect('127.0.0.1', 6379); if ($res == false) { return false; } else { return $redis; } } } ```