0 开启服务
0.1 查看php服务是否运行
service php-fpm status
如果未开启,可以设置开机自启动或者手动开启
service php-fpm start
0.2 启动容器
#查看容器 docker ps -a #启动容器 docker start xxxx #进入容器 docker exec -it 容器id /bin/sh
0/3 打开数据库
本地小皮 mysql服务开启
1 什么是池 基本结构 初始化本地连接池
https://www.bilibili.com/video/BV14E411t7T4?p=34&vd_source=4a69745b599dffec877b0fcfe130b092
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
1.1 新建项目
配置
项目初始化
composer init
修改compser.json
"autoload":{ "psr-4":{ "App\\":"app/" } }
composer dump-autoload
安装外部库 swoole-ide-helper
1.2 代码
1.2.1 抽象接口
\swoolepro\app\pool\DBPool.php
<?php namespace App\pool; abstract class DBPool { private $min; //最少放几个 private $max; //最多放几个 private $conns; //协程 abstract protected function newDB(); function __construct($min=5,$max=10) { $this->min = $min; $this->max = $max; //https://www.kancloud.cn/fage/swoole_extension/691372 //使用本地内存,不同的进程之间内存是隔离的。 //通道,类似于go语言的chan,支持多生产者协程和多消费者协程。底层自动实现了协程的切换和调度。 //Channel特点 //与容量有关 //如果channel未满,push不阻塞,如果已满,push让出控制流; //如果channel为空,pop让出控制流 $this->conns= new \Swoole\Coroutine\Channel($this->max); } /** * 根据最小连接数,初始化函数 */ public function initPool() { for ($i=0; $i<$this->min; $i++){ $db = $this->newDB(); $this->conns->push($db); } } }
1.2 POD连接
\seckill\swoolepro\app\pool\PDOPool.php
<?php namespace App\pool; //alt+回车 红色部分 自动生成 newDB class PDOPool extends DBPool { public function __construct(int $min = 5, int $max = 10) { parent::__construct($min, $max); \Swoole\Runtime::enableCoroutine(true); } protected function newDB() { // TODO: Implement newDB() method. $dsn = "mysql:host=10.10.10.114;dbname=test"; $pdo = new \PDO($dsn,'ttt','123456'); return $pdo; ;; } }
1.3启动
seckill\swoolepro\test.php
<?php require __DIR__."/vendor/autoload.php"; go(function (){ $pool = new \App\pool\PDOPool(); $pool->initPool(); while (true){ echo "链接了\n"; \Swoole\Coroutine::sleep(1); } });
1.4 测试
显示用户正在运行的线程
SHOW PROCESSLIST
- Id: 就是这个线程的唯一标识,当我们发现这个线程有问题的时候,可以通过 kill 命令,加上这个Id值将这个线程杀掉。前面我们说了show processlist 显示的信息时来自information_schema.processlist 表,所以这个Id就是这个表的主键。
- User: 就是指启动这个线程的用户。
- Host: 记录了发送请求的客户端的 IP 和 端口号。通过这些信息在排查问题的时候,我们可以定位到是哪个客户端的哪个进程发送的请求。
- DB: 当前执行的命令是在哪一个数据库上。如果没有指定数据库,则该值为 NULL 。
- Command: 是指此刻该线程正在执行的命令。这个很复杂,下面单独解释
- Time: 表示该线程处于当前状态的时间。
- State: 线程的状态,和 Command 对应,下面单独解释。
- Info: 一般记录的是线程执行的语句。默认只显示前100个字符,也就是你看到的语句可能是截断了的,要看全部信息,需要使用 show full processlist。
下面我们单独看一下 Command 的值:
- Binlog Dump: 主节点正在将二进制日志 ,同步到从节点
- Change User: 正在执行一个 change-user 的操作
- Close Stmt: 正在关闭一个Prepared Statement 对象
- Connect: 一个从节点连上了主节点
- Connect Out: 一个从节点正在连主节点
- Create DB: 正在执行一个create-database 的操作
- Daemon: 服务器内部线程,而不是来自客户端的链接
- Debug: 线程正在生成调试信息
- Delayed Insert: 该线程是一个延迟插入的处理程序
- Drop DB: 正在执行一个 drop-database 的操作
- Execute: 正在执行一个 Prepared Statement
- Fetch: 正在从Prepared Statement 中获取执行结果
- Field List: 正在获取表的列信息
- Init DB: 该线程正在选取一个默认的数据库
- Kill : 正在执行 kill 语句,杀死指定线程
- Long Data: 正在从Prepared Statement 中检索 long data
- Ping: 正在处理 server-ping 的请求
- Prepare: 该线程正在准备一个 Prepared Statement
- ProcessList: 该线程正在生成服务器线程相关信息
- Query: 该线程正在执行一个语句
- Quit: 该线程正在退出
- Refresh:该线程正在刷表,日志或缓存;或者在重置状态变量,或者在复制服务器信息
- Register Slave: 正在注册从节点
- Reset Stmt: 正在重置 prepared statement
- Set Option: 正在设置或重置客户端的 statement-execution 选项
- Shutdown: 正在关闭服务器
- Sleep: 正在等待客户端向它发送执行语句
- Statistics: 该线程正在生成 server-status 信息
- Table Dump: 正在发送表的内容到从服务器
- Time: Unused
2 从池中获取连接、放回连接
https://www.bilibili.com/video/BV14E411t7T4/?p=35&vd_source=4a69745b599dffec877b0fcfe130b092
2.1 代码
2.1.1 swoolepro\app\pool\PDOPool.php
<?php namespace App\pool; //alt+回车 红色部分 自动生成 newDB class PDOPool extends DBPool { public function __construct(int $min = 5, int $max = 10) { parent::__construct($min, $max); \Swoole\Runtime::enableCoroutine(true); } protected function newDB() { // TODO: Implement newDB() method. $dsn = "mysql:host=10.10.10.114;dbname=test"; $pdo = new \PDO($dsn,'ttt','123456'); return $pdo; } }
2.1.2 seckill\swoolepro\app\pool\CoMySqlPool.php
<?php namespace App\pool; class CoMySqlPool extends DBPool { public function __construct(int $min = 5, int $max = 10) { parent::__construct($min, $max); } protected function newDB() { // TODO: Implement newDB() method. $mysql = new \Swoole\Coroutine\MySQL(); $mysql ->connect([ 'host'=>'10.10.10.114', 'user'=>'ttt', 'password'=>'123456', 'database'=>'test' ]); return $mysql; } }
2.1.3 seckill\swoolepro\test.php
<?php require __DIR__."/vendor/autoload.php"; go(function (){ //$pool = new \App\pool\PDOPool(); $pool = new \App\pool\CoMySqlPool(); $pool->initPool(); for ($i=0;$i<5;$i++){ go(function () use($pool,$i){ $conn = $pool->getConnection(); //PDO在执行完后如果引用的conn数量为0,则会被释放(手动释放、把conn设置为null) //这并不符合连接池的要求,因为这样连接池就空了 defer(function () use ($pool,$conn){ //defer写在前 是怕后面的执行语句不一定成功 $pool->close($conn); // 放回链接 //channel对connection进行了引用 }); //pdo方式 /* $state = $conn->query(" select $i"); $state->setFetchMode(PDO::FETCH_ASSOC); $rows=$state->fetchAll(); var_dump($rows);*/ //mysqlCo方式 $state = $conn->query(" select $i"); var_dump($state); }); } while (true){ echo "链接了\n"; \Swoole\Coroutine::sleep(1); } });
3 取出连接时的判断(连接池空状态)
https://www.bilibili.com/video/BV14E411t7T4?p=36
3.1 代码
3.1.1 seckill\swoolepro\app\pool\DBPool.php
<?php namespace App\pool; /** * Class DBPool * @package App\pool * 连接池 */ abstract class DBPool { private $min; //最少放几个 private $max; //最多放几个 private $conns; //协程 private $count;//当前所有连接数 abstract protected function newDB(); function __construct($min=5,$max=10) { $this->min = $min; $this->max = $max; //https://www.kancloud.cn/fage/swoole_extension/691372 //使用本地内存,不同的进程之间内存是隔离的。 //通道,类似于go语言的chan,支持多生产者协程和多消费者协程。底层自动实现了协程的切换和调度。 //Channel特点 //与容量有关 //如果channel未满,push不阻塞,如果已满,push让出控制流; //如果channel为空,pop让出控制流 $this->conns= new \Swoole\Coroutine\Channel($this->max); } /** * 根据最小连接数,初始化函数 */ public function initPool() { for ($i=0; $i<$this->min; $i++){ $db = $this->newDB(); $this->conns->push($db); } $this->count = $this->min; } /** * 从连接池取出链接 * @return mixed */ public function getConnection() { //1 是否为空 //使用channel的isEmpty函数 //2 如果空,则要判断 // 如果再创建一个,当前连接数+1 // 判断当前连接数是否超过最大连接数 // (当前连接数不能用length判断,因为连接取出后还要放回) if($this->conns->isEmpty()){ if ($this->count<$this->max){ $db = $this->newDB(); $this->conns->push($db); $this->count ++; } } return $this->conns->pop(); } /** * 放回连接池 */ public function close($conn) { if ($conn){ //只要有引用,pdo就不会关闭 $this->conns->push($conn); } } }
4 取出连接时的判断(连接池满状态)
https://www.bilibili.com/video/BV14E411t7T4?p=37