<?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實現簡單的連接池
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.