<?php
namespace app\swoole\controller;
/**
* 通用的连接池
*/
abstract class Pool
{
/**
* 连接池的尺寸,最大连接数
* @var int $poolSize
*/
protected $poolSize;
/**
* 连接池的资源
* @var array $resourcePool
*/
protected $resourcePool = array();
protected $resourceNum = 0;
protected $failureCount = 0;
/**
* @var \SplQueue
*/
protected $idlePool;
/**
* @var \SplQueue
*/
protected $taskQueue;
protected $createFunction;
protected $config;
/**
* @param int $poolSize
* @param array $config
* @throws \Exception
*/
public function __construct($config = array(), $poolSize = 100)
{
$this->poolSize = $poolSize;
$this->taskQueue = new \SplQueue();
$this->idlePool = new \SplQueue();
$this->config = $config;
}
/**
* 加入到连接池中
* @param $resource
*/
public function join($resource)
{
//保存到空闲连接池中
$this->resourcePool[spl_object_hash($resource)] = $resource;
$this->release($resource);
}
/**
* 释放资源
* @param $resource
*/
public function release($resource)
{
$this->idlePool->enqueue($resource);
//有任务要做
if (count($this->taskQueue) > 0)
{
$this->doTask();
}
}
/**
* @param $callback
*/
public function create($callback)
{
$this->createFunction = $callback;
}
/**
* 失败计数
*/
public function failure()
{
$this->resourceNum--;
$this->failureCount++;
}
/**
* 修改连接池尺寸
* @param $newSize
*/
public function setPoolSize($newSize)
{
$this->poolSize = $newSize;
}
/**
* 移除资源
* @param $resource
* @return bool
*/
public function remove($resource)
{
$rid = spl_object_hash($resource);
if (!isset($this->resourcePool[$rid]))
{
return false;
}
//从resourcePool中删除
unset($this->resourcePool[$rid]);
$this->resourceNum--;
return true;
}
/**
* 请求资源
* @param callable $callback
* @return bool
*/
public function request(callable $callback)
{
// 1.先入taskQueue,再入idlePool队列
//入队列
$this->taskQueue->enqueue($callback);
//有可用资源
if (count($this->idlePool) > 0){
$this->doTask();
} elseif (count($this->resourcePool) < $this->poolSize && $this->resourceNum < $this->poolSize){
//没有可用的资源, 创建新的连接,直接调用到Swredis中的connect方法 连接swoole_redis
call_user_func($this->createFunction);
$this->resourceNum++;
}
}
// 查询连接池中是否存在可用的资源
protected function doTask()
{
$resource = null;
//从空闲队列中取出可用的资源
while (count($this->idlePool) > 0){
// 从连接池中拿取连接
$_resource = $this->idlePool->dequeue();
$rid = spl_object_hash($_resource);
//资源已经不可用了,连接已关闭
if (!isset($this->resourcePool[$rid])){
continue;
} else {
//找到可用连接
$resource = $_resource;
break;
}
}
//没有可用连接,继续等待
if (!$resource){
if (count($this->resourcePool) == 0){
call_user_func($this->createFunction);
$this->resourceNum++;
}
return;
}
// 已经拿到连接之后,将taskQueue任务队列中的首个连接踢出,表示已经拿了连接,完成了任务
$callback = $this->taskQueue->dequeue();
call_user_func($callback, $resource);
}
}
PHP实现简单的连接池
最新推荐文章于 2023-12-21 16:43:44 发布