以前過golang40行代碼實現通用協程池php
今天看了下swoole相關文檔,用PHP也實現了一個,因爲swoole
沒有golang
的select
,因此實現的有點簡單,可是實用性還能夠,經過工廠函數實現了通用性。html
swoole官方的協程池是用只能用在Redis。由於協程池代碼層耦合了Redis實例化邏輯。git
class RedisPool { /** * @var \Swoole\Coroutine\Channel */ protected $pool; /** * RedisPool constructor. * @param int $size 鏈接池的尺寸 */ function __construct($size = 100) { $this->pool = new Swoole\Coroutine\Channel($size); for ($i = 0; $i < $size; $i++) { $redis = new Swoole\Coroutine\Redis(); $res = $redis->connect('127.0.0.1', 6379); if ($res == false) { throw new RuntimeException("failed to connect redis server."); } else { $this->put($redis); } } } function put($redis) { $this->pool->push($redis); } function get() { return $this->pool->pop(); } }
利用工廠方法的改造以下:github
<?php /** * @author xialeistudio * @date 2019-05-20 */ namespace swoole\foundation\pool; use Swoole\Coroutine\Channel; /** * Swoole generic connection pool * Class Pool * @package swoole\foundation\pool */ class GenericPool { /** * @var int pool size */ private $size = 0; /** * @var callable construct a connection */ private $factory = null; /** * @var Channel */ private $channel = null; /** * GenericPool constructor. * @param int $size * @param callable $factory * @throws InvalidParamException */ public function __construct($size, callable $factory) { $this->size = $size; $this->factory = $factory; $this->init(); } /** * check pool config * @throws InvalidParamException */ private function init() { if ($this->size <= 0) { throw new InvalidParamException('The "size" property must be greater than zero.'); } if (empty($this->factory)) { throw new InvalidParamException('The "factory" property must be set.'); } if (!is_callable($this->factory)) { throw new InvalidParamException('The "factory" property must be callable.'); } $this->bootstrap(); } /** * bootstrap pool */ private function bootstrap() { $this->channel = new Channel($this->size); for ($i = 0; $i < $this->size; $i++) { $this->channel->push(call_user_func($this->factory)); } } /** * Acquire a connection * @param int $timeout * @return mixed */ public function acquire($timeout = 0) { return $this->channel->pop($timeout); } /** * Release a resource * @param mixed $resource */ public function release($resource) { $this->channel->push($resource); } }
咱們代碼裏面不關心建立鏈接的具體邏輯,只要調用工廠方法便可。golang
項目已經開源到githubhttps://github.com/swoole-foundation/swoole-poolredis