• Mysql协程连接池
    • 添加数据库配置
    • 注意
    • 基础使用
    • 自动回收
      • invoke
      • defer
    • 预创建链接

    Mysql协程连接池

    参考Demo: Pool连接池

    demo中有封装好的mysql连接池以及mysql类,复制demo中的MysqlPool.php和MysqlObject.php并放入App/Utility/Pool中即可使用

    添加数据库配置

    dev.php,produce.php中添加配置信息:

    1. /*################ MYSQL CONFIG ##################*/
    2. 'MYSQL' => [
    3. 'host' => '192.168.75.1',
    4. 'port' => '3306',
    5. 'user' => 'root',
    6. 'timeout' => '5',
    7. 'charset' => 'utf8mb4',
    8. 'password' => 'root',
    9. 'database' => 'cry',
    10. 'POOL_MAX_NUM' => '20',
    11. 'POOL_TIME_OUT' => '0.1',
    12. ],

    EasySwooleEvent.php的initialize方法中注册连接池对象(注意命名空间,新版本可以无需注册,自动注册)

    1. <?php
    2. // 注册mysql数据库连接池
    3. PoolManager::getInstance()->register(MysqlPool::class,Config::getInstance()->getConf('MYSQL.POOL_MAX_NUM'));
    4. //注册之后会返回conf配置,可继续配置,如果返回null代表注册失败

    可通过register返回的PoolConf对象去配置其他参数

    注意

    连接池不是跨进程的,进程间的连接池连接数是相互独立的,默认最大值是10个;如果开了4个worker,最大连接数可以达到40个。

    基础使用

    在控制器 通过mysql连接池获取mysql操作对象

    1. <?php
    2. /**
    3. * Created by PhpStorm.
    4. * User: Tioncico
    5. * Date: 2019/3/5 0005
    6. * Time: 21:07
    7. */
    8. namespace App\HttpController;
    9. use App\Utility\Pool\MysqlPool;
    10. use EasySwoole\Component\Pool\PoolManager;
    11. use EasySwoole\Http\AbstractInterface\Controller;
    12. class Index extends Controller
    13. {
    14. function index()
    15. {
    16. $db = PoolManager::getInstance()->getPool(MysqlPool::class)->getObj();
    17. $data = $db->get('test');
    18. //使用完毕需要回收
    19. PoolManager::getInstance()->getPool(MysqlPool::class)->recycleObj($db);
    20. $this->response()->write(json_encode($data));
    21. // TODO: Implement index() method.
    22. }
    23. }

    直接getobj时,可能会出现没有连接(返回null)的情况,需要增加判断

    用完mysql连接池对象之后记得用recycleObj回收(新版本可使用invoker.defer方法自动回收)

    1. <?php
    2. PoolManager::getInstance()->getPool(MysqlPool::class)->recycleObj($db);

    自动回收

    invoke

    可通过invoke静态方法直接从连接池取出一个连接,直接使用,回调函数结束后自动回收:

    1. <?php
    2. try {
    3. MysqlPool::invoke(function (MysqlObject $mysqlObject) {
    4. $model = new UserModel($mysqlObject);
    5. $model->insert(new UserBean($this->request()->getRequestParam()));
    6. });
    7. } catch (\Throwable $throwable) {
    8. $this->writeJson(Status::CODE_BAD_REQUEST, null, $throwable->getMessage());
    9. }catch (PoolEmpty $poolEmpty){
    10. $this->writeJson(Status::CODE_BAD_REQUEST, null, '没有链接可用');
    11. }catch (PoolUnRegister $poolUnRegister){
    12. $this->writeJson(Status::CODE_BAD_REQUEST, null, '连接池未注册');
    13. }

    defer

    使用defer方法直接获取一个连接池连接,直接使用,协程结束后自动回收:

    1. <?php
    2. $db = MysqlPool::defer();
    3. $model = new UserModel($db);
    4. $model->insert(new UserBean($this->request()->getRequestParam()));

    异常拦截,当invoke,defer调用,内部发生(连接不够,连接对象错误)等异常情况时,会抛出PoolEmpty和PoolException,可在控制器基类拦截或直接忽略,EasySwoole内部有做异常拦截处理,将直接拦截并返回错误到前端.

    只要使用以上两个方法,就无需关注连接回收问题,将自动回收

    预创建链接

    新增preload方法,可在程序启动后预创建连接,避免在启动时突然大量请求,造成连接来不及创建从而失败的问题.
    示例:
    在EasySwooleEvent文件,mainServerCreate事件中增加onWorkerStart回调事件中预热启动:

    1. <?php
    2. //注册onWorkerStart回调事件
    3. public static function mainServerCreate(EventRegister $register)
    4. {
    5. $register->add($register::onWorkerStart, function (\swoole_server $server, int $workerId) {
    6. if ($server->taskworker == false) {
    7. PoolManager::getInstance()->getPool(MysqlPool::class)->preLoad(1);
    8. //PoolManager::getInstance()->getPool(RedisPool::class)->preLoad(预创建数量,必须小于连接池最大数量);
    9. }
    10. // var_dump('worker:' . $workerId . 'start');
    11. });
    12. }