在PHP中,访问MySQL数据库往往是性能提升的瓶颈。而MySQL连接池我想大家都不陌生,这是一个很好的提升数据库访问性能的方式。传统的MySQL连接池,是预先申请一定数量的连接,每一个新的请求都会占用其中一个连接,请求结束后再将连接放回池中,如果所有连接都被占用,新来的连接则会进入等待状态。
知道了MySQL连接池的实现原理,那我们来看如何使用Swoole实现一个连接池。
首先,Swoole允许开启一定量的Task Worker进程,我们可以让每个进程都拥有一个MySQL连接,并保持这个连接,这样,我们就创建了一个连接池。
其次,设置swoole的dispatch_mode为抢占模式(主进程会根据Worker的忙闲状态选择投递,只会投递给处于闲置状态的Worker)。这样,每个task都会被投递给闲置的Task Worker。这样,我们保证了每个新的task都会被闲置的Task Worker处理,如果全部Task Worker都被占用,则会进入等待队列。
mysql连接默认等待时间(wait_timeout)是28800秒(8个小时),也就是说客户端建立一个连接,没有主动断开连接,也没有任何操作,MySQL会在到达设置的wait_timeout后断开这个连接。
问题由此产生,如果使用Swoole异步处理数据,长时间未发送数据给Swoole服务端,那么这个来连接就可能因超过wait_timeout等待时间而被MySQL强制关闭。
解决此问题,Swoole内置了心跳检测功能,而开启心跳检测功能,只需要设置heartbeat_check_interval和heartbeat_idle_time即可。
'heartbeat_idle_time' => 60, // 表示一个连接如果600秒内未向服务器发送任何数据,此连接将被强制关闭
'heartbeat_check_interval' => 10 // 表示每60秒遍历一次
但心跳检测功能仅支持TCP服务,这些参数对HTTP服务无效,所以最好的办法是手动创建一个心跳检测机制。
远离比较简单,做一个定时器,定时发送请求,保持MySQL连接,在启动Swoole的时候,同时启动定时器。
定时器要单独开启一个进程,否则会和单前的HTTP服务器冲突,并发出警告:
PHP Warning: Swoole\Server::start(): eventLoop has already been created, unable to start Swoole\Http\Server
正确做法:
use Swoole\Process;
$http = new Swoole\Http\Server("0.0.0.0", 9501);
//创建 子进程
$process = new Process(function () {
//默认定时器在执行回调函数时会自动创建协程
Swoole\Timer::tick(2000, function (int $timer_id) { //单位:毫秒
echo "coro-----1 " . Coroutine::getcid() . " start\n";
});
});
$http->addProcess($process);
时间原因,先记录这些。
参考文章:
https://blog.csdn.net/sunrj_niu/article/details/129706148
https://blog.csdn.net/weixin_33923762/article/details/92145939
https://developer.aliyun.com/article/1547450