PHP實現簡單的連接池

<?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);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章