链接池的含义,不少都知道,好比mysql的数据库链接是有限的,一开始链接mysql建立N个链接,放到一个容器里,每次有请求去容器中取出,取出用完再放回去。mysql
es3demo里,有mysql的链接池。sql
EasySwooleEvent::30行,执行initialize方法会注册一个MysqlPool::class
MysqlPool是继承于AbstractPool的只实现了createObject方法来建立mysql链接对象
AbstractPool这个抽象类,里咱们分析下2个函数getObj和recycleObj。
EasySwoole\Component\Pool\AbstractPool::35和57行
getObj函数,当协程的chan仍是空的时候不必定指的是初始化,多是链接池的mysql链接都被用光了还没被回收,举个例子,若是个人链接池容量是10,如今10个用户同时访问我,我从链接池取出了10个如今链接池空了,等10我的随便某人用完了回收,链接池又不空了。这样就能理解为何还
要判断当前建立的数量是否大于链接池容量。若是没有大于说明如今还能够继续往容器里防止链接对象而不会溢出链接池容量。其余状况就直接尝试从chan取出链接池对象。若是获取失败也是容许的。并发场景下获取不到链接池能容忍。
public function getObj(float $timeout = 0.1) { //懒惰建立模式 $obj = null; if($this->chan->isEmpty()){ //若是尚未达到最大链接数,则尝试进行建立 if($this->createdNum < $this->max){ $this->createdNum++; $obj = $this->createObject(); if(!is_object($obj)){ $this->createdNum--; //建立失败,一样进入调度等待 $obj = $this->chan->pop($timeout); } }else{ $obj = $this->chan->pop($timeout); } }else{ $obj = $this->chan->pop($timeout); } //对对象进行标记处理 if(is_object($obj)){ $key = spl_object_hash($obj); //标记这个对象已经出队列了 $this->objHash[$key] = true; $obj->last_use_time = time(); return $obj; }else{ return null; } }
回收的话就简单了,把获取到链接池对象塞回去chan->push数据库
public function recycleObj($obj):bool { if(is_object($obj)){ //防止一个对象被重复入队列。 $key = spl_object_hash($obj); if(isset($this->objHash[$key])){ //标记这个对象已经入队列了 unset($this->objHash[$key]); if($obj instanceof PoolObjectInterface){ $obj->objectRestore(); } $obj->last_recycle_time = time(); $this->chan->push($obj); return true; }else{ return false; } }else{ return false; } }
示例demo是这样调用的并发
App\HttpController\Api1构造方法会去从链接池里获取数据库链接,而后afterAction会去调用recycleObject进行回收。