MySQL数据库对每个客户端连接都会分配一个线程,所以连接非常宝贵。开发一个异步的MySQL代理服务器,PHP应用服务器可以长连接到这台Server,既减轻MYSQL的连接压力,又使PHP保持长连接减少connect/close的网络开销。

此Server考虑到了设置了数据库连接池尺寸,区分忙闲,mysqli断线重连,并设置了负载保护。基于swoole扩展开发,io循环使用epoll,是全异步非阻塞的,可以应对大量TCP连接。

程序的逻辑是:启动时创建N个MySQL连接,收到客户端发来的SQL后,分配1个MySQL连接,将SQL发往数据库服务器。然后等待数据库返回查询结果。当数据库返回结果后,再发给对应的客户端连接。

核心的数据结构是3个PHP数组。idle_pool是空闲的数据库连接,当有SQL请求时从idle_pool中移到busy_pool中。当数据库返回结果后从busy_pool中再移到idle_pool中,以供新的请求使用。当SQL请求到达时如果没有空闲的数据库连接,那会自动加入到wait_queue中。一旦有SQL完成操作,将自动从wait_queue中取出等待的请求进行处理。

如此循环使用。由于整个服务器是异步的单进程单线程所以完全不需要锁。而且是完全异步的,效率非常高。

当然本文的代码,如果要用于生产环境,还需做更多的保护机制和压力测试。在此仅抛砖引玉,提供一个解决问题的思路。

class DBServer

{

protected $pool_size = 20;

protected $idle_pool = array(); //空闲连接

protected $busy_pool = array(); //工作连接

protected $wait_queue = array(); //等待的请求

protected $wait_queue_max = 100; //等待队列的最大长度,超过后将拒绝新的请求

/**

* @var swoole_server

*/

protected $serv;

function run()

{

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

$serv->set(array(

'worker_num' => 1,

));

$serv->on('WorkerStart', array($this, 'onStart'));

//$serv->on('Connect', array($this, 'onConnect'));

$serv->on('Receive', array($this, 'onReceive'));

//$serv->on('Close', array($this, 'onClose'));

$serv->start();

}

function onStart($serv)

{

$this->serv = $serv;

for ($i = 0; $i < $this->pool_size; $i++) {

$db = new mysqli;

$db->connect('127.0.0.1', 'root', 'root', 'test');

$db_sock = swoole_get_mysqli_sock($db);

swoole_event_add($db_sock, array($this, 'onSQLReady'));

$this->idle_pool[] = array(

'mysqli' => $db,

'db_sock' => $db_sock,

'fd' => 0,

);

}

echo "Server: start.Swoole version is [" . SWOOLE_VERSION . "]\n";

}

function onSQLReady($db_sock)

{

$db_res = $this->busy_pool[$db_sock];

$mysqli = $db_res['mysqli'];

$fd = $db_res['fd'];

echo __METHOD__ . ": client_sock=$fd|db_sock=$db_sock\n";

if ($result = $mysqli->reap_async_query()) {

$ret = var_export($result->fetch_all(MYSQLI_ASSOC), true) . "\n";

$this->serv->send($fd, $ret);

if (is_object($result)) {

mysqli_free_result($result);

}

} else {

$this->serv->send($fd, sprintf("MySQLi Error: %s\n", mysqli_error($mysqli)));

}

//release mysqli object

$this->idle_pool[] = $db_res;

unset($this->busy_pool[$db_sock]);

//这里可以取出一个等待请求

if (count($this->wait_queue) > 0) {

$idle_n = count($this->idle_pool);

for ($i = 0; $i < $idle_n; $i++) {

$req = array_shift($this->wait_queue);

$this->doQuery($req['fd'], $req['sql']);

}

}

}

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

{

//没有空闲的数据库连接

if (count($this->idle_pool) == 0) {

//等待队列未满

if (count($this->wait_queue) < $this->wait_queue_max) {

$this->wait_queue[] = array(

'fd' => $fd,

'sql' => $data,

);

} else {

$this->serv->send($fd, "request too many, Please try again later.");

}

} else {

$this->doQuery($fd, $data);

}

}

function doQuery($fd, $sql)

{

//从空闲池中移除

$db = array_pop($this->idle_pool);

/**

* @var mysqli

*/

$mysqli = $db['mysqli'];

for ($i = 0; $i < 2; $i++) {

$result = $mysqli->query($sql, MYSQLI_ASYNC);

if ($result === false) {

if ($mysqli->errno == 2013 or $mysqli->errno == 2006) {

$mysqli->close();

$r = $mysqli->connect();

if ($r === true) continue;

}

}

break;

}

$db['fd'] = $fd;

//加入工作池中

$this->busy_pool[$db['db_sock']] = $db;

}

}

$server = new DBServer();

$server->run();

读者们如果觉得还可以就帮忙点个赞 蟹蟹

另外读者福利,可直接点击链接领取相关学习福利包:PHP高薪就业(视频、学习路线、免费获取)​www.jianshu.com

是安全网站放心,继续访问就可以领取了哦

转发开源

mysql异步扩展_基于Swoole扩展开发异步高性能的MySQL代理服务器相关推荐

  1. mysql for循环_基于Swoole扩展开发异步高性能的MySQL代理服务器

    MySQL数据库对每个客户端连接都会分配一个线程,所以连接非常宝贵.开发一个异步的MySQL代理服务器,PHP应用服务器可以长连接到这台Server,既减轻MYSQL的连接压力,又使PHP保持长连接减 ...

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

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

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

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

  4. sqlsugar对mysql效率高_基于.Net Core 2.0 + SqlSugar ORM + MySql快速实现网站开发

    .Net Core 2.0 (以下简称Core)正式版已经发布有一段时间了, 博主也第一时间尝鲜了, 相比Core 1.0和1.1类库支持方面提高了不少, 开发起来也方便快捷很多了. 废话不多说了, ...

  5. java 异步框架_基于Java的轻量级异步编程框架

    # **DActor** ## Introduction DActor框架可同时支持同步和异步代码,简化在线异步代码的开发,用同步代码的思维来开发异步代码,兼顾异步代码的高并发.无阻塞和同步代码的易读 ...

  6. 使用php开发,基于swoole扩展开发的工具 swoole-crontab

    2019独角兽企业重金招聘Python工程师标准>>> 使用php开发,基于swoole扩展开发的工具 swoole-crontab https://www.oschina.net/ ...

  7. Arduino开发(二)_基于Arduino UNO开发板的RGB灯光控制方法

    Arduino开发(二)_基于Arduino UNO开发板的RGB灯光控制方法 首先,我们来看一下Arduino UNO开发板的具体引脚排列,如下图所示, 再了解一下三色RGB LED模块,如下图所示 ...

  8. macos big sur安装php扩展_用PHP构建基于swoole扩展的socket服务(附PHP扩展安装步骤)...

    最近公司的一项目中,需要用PHP搭建一个socket服务. 本来PHP是不适合做服务的,因为和第三方合作,需要采用高效而稳定的TCP协议进行数据通信.经过多次尝试,最终选择了开源的PHP扩展:swoo ...

  9. go 连接服务器 并存放图片_基于 Go 语言开发在线论坛(二):通过模型类与MySQL数据库交互...

    在这篇教程中,我们将在 MySQL 中创建一个 chitchat 数据库作为论坛项目的数据库,然后在 Go 项目中编写模型类与之进行交互.你可以本地安装 MySQL 数据库,也可以基于 Docker ...

最新文章

  1. 基于深度卷积神经网络的循环优化操作和FPGA加速中的数据流
  2. Hadoop数据倾斜及解决办法
  3. android vivox21 适配,还在苦等Android P的适配?原来这些功能vivo X21早都有了
  4. 为什么按照 Angular 官网教程执行简单的测试代码,会遇到expect is not defined的错误消息
  5. easyplayerpro 使用说明_EasyPlayerPro(Windows)流媒体播放器开发之ffmpeg log输出报错
  6. Oracle学习(一)SQL基础
  7. 爬虫-腾讯视频-弹幕评论
  8. potala(5)——Unit Test and Cache
  9. 51Nod-1015 水仙花数【进制+查表搜索】
  10. postgresql 9.1 基于wal的 pitr 恢复
  11. 小米发布会之文案错误:大哥你先处罚自己!再处罚相关高管!
  12. 伍楼阁使用的WordPress代码高亮插件使用说明
  13. openmeeting开发心得及相关文档
  14. python曲线和直线的交点_求直线与分段线性曲线的交点
  15. 进度计划中的时间相关术语
  16. opendrive简介
  17. bat脚本——提取多个文件夹到指定路径
  18. 【Python爬虫】你还在纠结选择哪个爬虫库嘛,全都拿来吧你
  19. 《Java170道面试笔试题全面含答案》
  20. YOLOV3预选框验证

热门文章

  1. Office 365和SFB更新
  2. 学习Key与Value的集合hashtable
  3. 云时代看CRM如何引领企业成功?
  4. 【BZOJ1497】【NOI2006】最大获利
  5. OC基础数据类型-NSData-NSMutableData-NSString
  6. 关于arm处理器 内存编址模式 与 字节对齐方式 (转)
  7. innodb和myisam
  8. Qt应用程序主窗口之一:主窗口框架
  9. spring-cloud-config安全问题
  10. P3398仓鼠(LCA)