## 连接池的意义
对于基于php-fpm的传统php-web应用,包括且不限于Mysql,Redis,RabbitMq,每次请求到来都需要为其新建一套独享的的连接,这直接带来了一些典型问题:
1. **连接开销** : 连接随着http请求到来而新建,随着请求返回而销毁,大量连接新建销毁是对系统资源的浪费。
2. **连接数量过高** :每一个请求都需要一套自己的连接,系统连接数和并发数会成一个近线性的关系。如果系统并发量达到了1w,那么就需要建立1w个对应的连接,这对于Mysql之类的后端服务而言,是一个大的负荷。
3. **空闲连接**:假设我们有一个接口使用了一个Mysql连接。该接口在一开始进行一次sql查询后,后面的操作都是sql无关的,那么该请求占据的空闲连接完全就是一种资源的浪费。
对于异步系统而言,这个问题变得更加的严峻。一个请求处理进程要对同一个服务进行并发的操作,意味着这个请求要持有1个以上同类的连接,这对于系统压力而言,无疑是雪上加霜了,所以连接池对于基于Swoole的Web框架而言已经是一个必需实现的机制了。事实上基本所有的框架都内置了连接池管理机制,比如 [easyswoole Pool管理器](http://www.easyswoole.com/Manual/3.x/Cn/_book/Components/CoroutinePool/pool.html),[swoft 连接池](https://doc.swoft.org/master/zh-CN/core/connection-pool.html) 等等。
## 实现Mysql连接池
一个基本连接池,大致要实现以下功能:
1. 创建连接:连接池启动后,初始化一定的空闲连接,指定为最少的连接min。当连接池为空,不够用时,创建新的连接放到池里,但不能超过指定的最大连接max数量。
2. 连接释放:每次使用完连接,一定要调用释放方法,把连接放回池中,给其他程序或请求使用。
3. 连接分配:连接池中用pop和push的方式对等入队和出队分配与回收。能实现阻塞分配,也就是在池空并且已创建数量大于max,阻塞一定时间等待其他请求的连接释放,超时则返回null。
4. 连接管理:对连接池中的连接,定时检活和释放空闲连接等。
**连接池管理器**
~~~
/**
* 连接池抽象类
*/
use Swoole\Coroutine\Channel;
abstract class AbstractPool
{
private $min;//最少连接数
private $max;//最大连接数
private $count;//当前连接数
private $connections;//连接池组
protected $spareTime;//用于空闲连接回收判断
private $inited = false;
protected abstract function createDb();
public function __construct()
{
$this->min = 10;
$this->max = 100;
$this->spareTime = 10 * 3600;
$this->connections = new Channel($