背景:swoole的出现,包括PHP出现前,在新浪企业邮箱就有基于Sun Solaris 系统上面用c++写Mysql的长连接,那时候的长连接是基于RPC实现,对mysql那一端形成一个远程过程的调用,通过XDR数据结构进行解析mysql传来的数据项(RPC也为sun最新提出并后来在linux上默认支持),也就是说像用户登录验证这一块用Mysql的长连接来实现,提高其效率运行相当稳定,后面这个系统迁移到了FreeBSD后,出现了mysql长连接的服务经常出现假死,也就是说进程还在,但是已经连接不上mysql了,重新启动这个RPC服务又好了,原因未知,当时我对c++不了解(现在也不太了解,只听说要看是否形成coredump啥的),当年我还写过一个判断死了就杀死,重启动,判断的程序也老半天回不来,于是我又改成了一个多进程,如果超时没有回来,就干掉那个进程,重启Rpc服务,再后来,这套C++的cgi被替换成了php,再后来基于FreeBSD的系统迁移到了Linux,也就是现在一直在linux上,linux也就强大了起来,回想起来,当年一个登录服务如此极致,现在都变成了直接查询mysql了,这个长连接技术有还有用吗?我只能说对有上千台上万台的服务器可能有用,能节省一定的机器成本罢。但是,追求技术永无止境,需要有这样的一些东西来繁荣我们这个PHP的市场,长连接这个话题不再是Java做成了连接池,像c++也能做成连接池,像腾讯广平就有c++团队还有写cgi实现长连接Mysql服务,据说前二年吧更多关注了H5,像实时技术,比如Tail技术在web上的实现,有转向nodejs的趋势,而此时的PHP拿不出这样的技术,是很危险的,有了swoole起到填补作用,我更多的是觉得官方应该重视这个技术,而不是形成一个扩展,像H5的来到,像websocket的进入,这些东西对于Node来讲,从前端向后端的统一,而PHp呢?没有谁来解决,那么从用户角度来讲,开发者用户的流失或迁移,对PHP本身也是一个损失,但我还是说PHP是最好的语言没有之一,期望其能伴随潮流,与时俱进。

PHP的数据库连接池一直以来都是一个难题,很多从PHP语言转向Java的项目,大多数原因都是因为Java有更好的连接池实现。PHP的MySQL扩展提供了长连接的API,但在PHP机器数量较多,规模较大的情况下,mysql_pconnect非但不能节约MySQL资源,反而会加剧数据库的负荷。

假设有100台PHP的应用服务器,每个机器需要启动100个apache或fpm工作进程,那每个进程都会产生一个长连接到MySQL。这一共会产生1万个My SQL连接。大家都知道MySQL是每个连接会占用1个线程。那MYSQL就需要创建1万个线程,这样大量的系统资源被浪费在线程间上下文切换上。而你的业务代码中并不是所有地方都在做数据库操作,所以这个就是浪费的。

连接池就不同了,100个worker进程,公用10个数据库连接即可,当操作完数据库后,立即释放资源给其他worker进程。这样就算有100台PHP的服务器,那也只会创建1000个MySQL的连接,完全可以接受的。

以前确实没有好的办法来解决此问题的,现在有了swoole扩展,利用swoole提供的task功能可以很方便做出一个连接池来。

代码如下:

$serv = new swoole_server("127.0.0.1", 9508);

$serv->set(array(

'worker_num' => 100,

'task_worker_num' => 10, //MySQL连接的数量

));

function my_onReceive($serv, $fd, $from_id, $data)

{

//taskwait就是投递一条任务,这里直接传递SQL语句了

//然后阻塞等待SQL完成

$result = $serv->taskwait("show tables");

if ($result !== false) {

list($status, $db_res) = explode(':', $result, 2);

if ($status == 'OK') {

//数据库操作成功了,执行业务逻辑代码,这里就自动释放掉MySQL连接的占用

$serv->send($fd, var_export(unserialize($db_res), true) . "\n");

} else {

$serv->send($fd, $db_res);

}

return;

} else {

$serv->send($fd, "Error. Task timeout\n");

}

}

function my_onTask($serv, $task_id, $from_id, $sql)

{

static $link = null;

if ($link == null) {

$link = mysqli_connect("127.0.0.1", "root", "root", "test");

if (!$link) {

$link = null;

$serv->finish("ER:" . mysqli_error($link));

return;

}

}

$result = $link->query($sql);

if (!$result) {

$serv->finish("ER:" . mysqli_error($link));

return;

}

$data = $result->fetch_all(MYSQLI_ASSOC);

$serv->finish("OK:" . serialize($data));

}

function my_onFinish($serv, $data)

{

echo "AsyncTask Finish:Connect.PID=" . posix_getpid() . PHP_EOL;

}

$serv->on('Receive', 'my_onReceive');

$serv->on('Task', 'my_onTask');

$serv->on('Finish', 'my_onFinish');

$serv->start();

看完上面的,看完了,觉得真的很厉害。毕竟,现在来说可能是还没有真正在PHP使用数据库连接池的大应用。今天终于准备实验实验。

在开始之前,还是说一下测试环境吧:OS CentOS 6.4 x86;php 5.3.17;MySQL 5.5.28;Swoole 1.6.8。

首先,我们当然要把代码写好。下面是服务端代码,很多是参考了上面文章里面的,当然也有自己的内容。

$serv = swoole_server_create('127.0.0.1', 3305, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);//端口3305

swoole_server_set($serv, array(

'worker_num' => 2,      //worker线程的数量

'task_worker_num' => 1, //MySQL连接的数量

));//作为小型测试,参数调得比较小

//这里有一个守护进程化的参数,由于是实验,没有加入

function my_onReceive($serv, $fd, $from_id, $data){

//执行查询

$result = $serv->taskwait($data);

if ($result !== false) {

swoole_server_send($serv, $fd, $result);

return;

} else {

swoole_server_send($serv, $fd, "Error. Task timeout\n");

}

}

function my_onTask($serv, $task_id, $from_id, $sql){

static $link = NULL;

if ($link == NULL) {

$link = mysqli_connect('localhost', 'user', 'pw', 'db');

//localhost=>UNIX Socket , IP地址=>TCP/IP

}

$result = $link->query($sql);

if ($result === false) {

swoole_server_finish($serv, 'b:0;');//语句运行失败,这是serialize后的false,下同理

return;

}

if ($result === true){

swoole_server_finish($serv, 'b:1;');//写入操作成功

return;

}

$data = $result->fetch_all(MYSQLI_ASSOC);

swoole_server_finish($serv, serialize($data));

}

function my_onFinish($serv, $data){

//这次实验就没有写东西了

//但是必须有这个函数定义

//其实可以写日志什么的吧

}

swoole_server_handler($serv, 'onReceive', 'my_onReceive');

swoole_server_handler($serv, 'onTask', 'my_onTask');

swoole_server_handler($serv, 'onFinish', 'my_onFinish');

//上面是设置回调函数

swoole_server_start($serv);

swoole_event_wait();//实验环境是PHP5.3,所以需要这个函数进行事件轮询;5.4+就不需要了

如果把上面的连接池代码和Rango的相比较,会发现我的对于错误的部分处理很少。其实这个时候用CLI运行这个连接池,然后使用Telnet已经就可以直接测试效果了。但是不管怎么说这个东西还是要应用在PHP上面的,我简单地写一下PHP方面的代码。

$link=new swoole_client(SWOOLE_SOCK_TCP,SWOOLE_SOCK_SYNC);//TCP方式、同步

$link->connect('127.0.0.1',3305);//连接

$link->send('SELECT * FROM `table`');//执行查询

$res=unserialize($link->recv());

if(!res){

echo 'Failed!';

}

else{

print_r($res);

}

$link->close();

//上面的是最简单的测试,下面可以简单地改写成函数

function dbcp_query($sql){

$link=new swoole_client(SWOOLE_SOCK_TCP,SWOOLE_SOCK_SYNC);//TCP方式、同步

$link->connect('127.0.0.1',3305);//连接

$link->send($sql);//执行查询

return unserialize($link->recv());

//swoole_client类析构时会自动关闭连接

}

现在可以运行了,本次实验是成功的。但是如果使用dbcp_query()这个函数,每次调用都要发起一次TCP连接,执行的语句多了,肯定出问题。这个时候我们就可以把它封装成一个类了,单纯实现这个会比较的简单,但是打出来要点时间,这里就不写了。

最后:今天做的是数据库连接池的实现。从上面的代码我们可以看见,程序与连接池之间的数据交换是使用php序列进行的。这里会有两次的serialize、unserialize,绝对也是一个开销。Rango的文章里面有说到“MySQL是每个连接会占用1个线程……大量的系统资源被浪费在线程间上下文切换上……不是所有地方都在做数据库操作,所以这个就是浪费的。”再看看他那篇文章的假设:“假设有100台PHP的应用服务器,每个机器需要启动100个apache或fpm工作进程。”这肯定不是一个小项目,确实就适合用连接池了。写的东西是用来练手或者解闷儿的?常规方法已经可以了。不要忘了一点:程序与连接池的交互我们应该还是用Swoole实现的,Swoole可是一个TCP/UDP扩展。而Swoole只能运行在Linux平台上面,但是Linux平台上的MySQL是可以用UNIX Socket通讯的。

P.S.:找个时间给epdb改写一个支持数据库连接池的版本。

来自:http://rango.swoole.com/archives/265

http://bokjan.com/prog/php-db-conn-pool-with-swoole.html

php cli swoole mysql_[了解实践]Swoole、PHP与MySQL:连接池,swoole扩展实现真正的PHP数据库连接池。...相关推荐

  1. php 协程 mysql_实现一个协程版mysql连接池

    实现一个协程版的mysql连接池,该连接池支持自动创建最小连接数,自动检测mysql健康:基于swoole的chanel. 最近事情忙,心态也有点不积极.技术倒是没有落下,只是越来越不想写博客了.想到 ...

  2. swoole task MySQL连接池

    参考 https://blog.csdn.net/ldy3243942/article/details/40596547 上一章中我简单讲解了如何开启和使用Task功能.这一节,我将提供一个Task的 ...

  3. PHP如何解决swoole守护进程Redis假死 ,mysql断线重连问题?

    PHP如何解决swoole守护进程Redis假死 ,mysql断线重连问题? 最近公司有个项目,要举办一个线上活动,我这边负责提供接口记录用户访问记录,与操作记录,由于活动参与人数可能比较多,为了不影 ...

  4. swoole实现数据库连接池

    2019独角兽企业重金招聘Python工程师标准>>> 原生 PHP CURD 让我们来回顾一下PHP中数据库的使用 <?php # curd.php$id = 1;$dbh ...

  5. mysql连接池_基于Swoole的通用连接池 - 数据库连接池(life)

    open-smf/connection-pool 是一个基于Swoole的通用连接池,常被用作数据库连接池. 依赖 依赖版本PHP>=7.0.0Swoole>=4.2.9Recommend ...

  6. swoole mysql 并发_Swoole4 如何打造高并发的PHP7协程Mysql连接池?

    一.数据库连接池基本概念 所谓的数据库连接池,一般指的就是程序和数据库保持一定数量的数据库连接不断开,并且各请求的连接可以相互复用,减少重复新建数据库连接的消耗和避免在高并发的情况下出现数据库max ...

  7. swoole原生mysql进程池_swoole的mysql连接池怎么弄

    swoole的mysql连接池怎么弄 发布时间:2020-12-28 09:54:07 来源:亿速云 阅读:68 作者:小新 这篇文章给大家分享的是有关swoole的mysql连接池怎么弄的内容.小编 ...

  8. easyswoole数据库连接池_如何在 Swoole 中优雅的实现 MySQL 连接池

    如何在 Swoole 中优雅的实现 MySQL 连接池 一.为什么需要连接池 ? 数据库连接池指的是程序和数据库之间保持一定数量的连接不断开, 并且各个请求的连接可以相互复用, 减少重复连接数据库带来 ...

  9. swoole mysql 连接池_基于Swoole的通用连接池 - 数据库连接池

    连接池 open-smf/connection-pool 是一个基于Swoole的通用连接池,常被用作数据库连接池. 依赖 依赖 版本 >=7.0.0 >=4.2.9 Recommend ...

最新文章

  1. Linux下MySql出现#1036 – Table ‘ ‘ is read only 错误解决方法
  2. 2019届宝鸡理数质检Ⅰ解析版
  3. jdbc和jdbc驱动_JDBC布尔兼容性列表
  4. MyEclipse2015Stable2.0安装破解
  5. android新建项目错误,新建Android项目出错
  6. Spring Cloud构建微服务架构:服务注册与发现(Eureka、Consul)
  7. C#~异步编程再续~你必须要知道的ThreadPool里的throw
  8. js里面关于IE和万恶的IE6的判断
  9. 00 后 CEO 何以“将马云和马化腾两家一网打尽”
  10. C++ 中的sort()排序函数用法
  11. 二级c语言试卷合集pdf,全国计算机二级C语言历年真题完整版.pdf
  12. 数据结构1800题-错题集-第二章
  13. 2022全新抖音二维码生成工具源码+亲测可用
  14. 【渝粤题库】广东开放大学 期货与期权 形成性考核
  15. html种颜色的三种不同表示方法,html网页背景颜色的代码是什么?颜色有几种表示方法?...
  16. vanta.js的使用(前端网站动态背景)
  17. 多元微积分(一)--导数与偏导数
  18. LWN:在进程级别完成内核相同页面合并(KSM)控制!
  19. iPhone游戏开发:使用到的工具和技术
  20. 关于模拟信号,数字信号,电磁波,基带传输的一点点感悟

热门文章

  1. .Net轻量状态机Stateless
  2. 《ASP.NET Core 微服务实战》译者序
  3. eShopOnContainers 看微服务④:Catalog Service
  4. 这个拖后腿的“in”
  5. Microsoft的现代数据管理
  6. CentOS上安装SQL Server vNext CTP1
  7. ubuntu16.4下用jexus部署asp.net core rtm
  8. ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件)
  9. 有人撸了个网页版win11,惊艳!
  10. [转]从入门到精通,Java学习路线导航