参考 https://blog.csdn.net/ldy3243942/article/details/40596547

上一章中我简单讲解了如何开启和使用Task功能。这一节,我将提供一个Task的高级用法。

在PHP中,访问MySQL数据库往往是性能提升的瓶颈。而MySQL连接池我想大家都不陌生,这是一个很好的提升数据库访问性能的方式。传统的MySQL连接池,是预先申请一定数量的连接,每一个新的请求都会占用其中一个连接,请求结束后再将连接放回池中,如果所有连接都被占用,新来的连接则会进入等待状态。
知道了MySQL连接池的实现原理,那我们来看如何使用Swoole实现一个连接池。
首先,Swoole允许开启一定量的Task Worker进程,我们可以让每个进程都拥有一个MySQL连接,并保持这个连接,这样,我们就创建了一个连接池。
其次,设置swoole的dispatch_mode为抢占模式(主进程会根据Worker的忙闲状态选择投递,只会投递给处于闲置状态的Worker)。这样,每个task都会被投递给闲置的Task Worker。这样,我们保证了每个新的task都会被闲置的Task Worker处理,如果全部Task Worker都被占用,则会进入等待队列。

下面直接上关键代码:

public function onWorkerStart( $serv , $worker_id) {echo "onWorkerStart\n";// 判定是否为Task Worker进程if( $worker_id >= $serv->setting['worker_num'] ) {$this->pdo = new PDO("mysql:host=localhost;port=3306;dbname=Test", "root", "123456", array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8';",PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::ATTR_PERSISTENT => true));}
}

首先,在每个Task Worker进程中,创建一个MySQL连接。这里我选用了PDO扩展。

public function onReceive( swoole_server $serv, $fd, $from_id, $data ) {$sql = array('sql'=>'select * from Test where pid > ?','param' => array(0),'fd' => $fd);$serv->task( json_encode($sql) );
}

其次,在需要的时候,通过task函数投递一个任务(也就是发起一次SQL请求)

public function onTask($serv,$task_id,$from_id, $data) {$sql = json_decode( $data , true );$statement = $this->pdo->prepare($sql['sql']);$statement->execute($sql['param']);     $result = $statement->fetchAll(PDO::FETCH_ASSOC);$serv->send( $sql['fd'],json_encode($result));return true;
}

最后,在onTask回调中,根据请求过来的SQL语句以及相应的参数,发起一次MySQL请求,并将获取到的结果通过send发送给客户端(或者通过return返回给Worker进程)。而且,这样的一次MySQL请求还不会阻塞Worker进程,Worker进程可以继续处理其他的逻辑。

可以看到,简单十几行代码,就实现了一个高效的异步MySQL连接池。
通过测试,单个客户端一共发起1W次select请求,共耗时9s;
1W次insert请求,共耗时21s。

(客户端会在每次收到前一个请求的结果后才会发起下一次请求,而不是并发)。

上面是原文 下面是代码

<?php
class MySQLPool
{public function __construct() {$this->serv = new swoole_server("0.0.0.0", 9501);$this->serv->set(array('worker_num' => 4,'daemonize' => false,'max_request' => 10000,'dispatch_mode' => 3,//这个模式下无法收到onclose这样的事件'debug_mode'=> 1 ,'task_worker_num' => 4));
/*
dispatch_mode
数据包分发策略。可以选择3种类型,默认为21,轮循模式,收到会轮循分配给每一个worker进程
2,固定模式,根据连接的文件描述符分配worker。这样可以保证同一个连接发来的数据只会被同一个worker处理
3,抢占模式,主进程会根据Worker的忙闲状态选择投递,只会投递给处于闲置状态的Worker
使用建议
无状态Server可以使用1或3,同步阻塞Server使用3,异步非阻塞Server使用1
有状态使用2、4、5
dispatch_mode 4,5两种模式,在1.7.8以上版本可用
非请求响应式的服务器程序,请不要使用模式1或3UDP协议
dispatch_mode=1/3时随机分配到不同的worker进程
BASE模式
*/$this->serv->on('WorkerStart', array($this, 'onWorkerStart'));$this->serv->on('Connect', array($this, 'onConnect'));$this->serv->on('Receive', array($this, 'onReceive'));$this->serv->on('Close', array($this, 'onClose'));// bind callback$this->serv->on('Task', array($this, 'onTask'));$this->serv->on('Finish', array($this, 'onFinish'));$this->serv->start();}public function onWorkerStart( $serv , $worker_id) {echo "onWorkerStart\n";// 判定是否为Task Worker进程if( $worker_id >= $serv->setting['worker_num'] ) {$this->pdo = new PDO("mysql:host=localhost;port=3306;dbname=testxcx","root","111111",array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8';",PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::ATTR_PERSISTENT => true));}}public function onConnect( $serv, $fd, $from_id ) {echo "Client {$fd} connect\n";}public function onReceive( swoole_server $serv, $fd, $from_id, $data ) {$sql = array('sql'=>'insert into test values(?,?)','param' => array(0 ,"name"),'fd' => $fd);$serv->task( json_encode($sql) );}public function onClose( $serv, $fd, $from_id ) {echo "a\n";echo "Client {$fd} close connection\n";}public function onTask($serv,$task_id,$from_id, $data) {try{$sql = json_decode( $data , true );//print_r($sql);
/*
Array
([sql] => insert into test values(?,?)[param] => Array([0] => 0[1] => name)[fd] => 1
)*/$statement = $this->pdo->prepare($sql['sql']);// $statement->execute($sql['param'][0],$sql['param'][1]);$statement->execute($sql['param']);$serv->send( $sql['fd'],"Insert");return true;} catch( PDOException $e ) {var_dump( $e );return false;}}public function onFinish($serv,$task_id, $data) {}
}
new MySQLPool();

上面是server 下面是client

<?php
class Client
{private $client;private $i = 0;private $time;public function __construct() {$this->client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);$this->client->on('Connect', array($this, 'onConnect'));$this->client->on('Receive', array($this, 'onReceive'));$this->client->on('Close', array($this, 'onClose'));$this->client->on('Error', array($this, 'onError'));}public function connect() {$fp = $this->client->connect("127.0.0.1", 9501 , 1);if( !$fp ) {echo "Error: {$fp->errMsg}[{$fp->errCode}]\n";return;}}public function onReceive( $cli, $data ) {$this->i ++;if( $this->i >= 10000 ) {echo "Use Time: " . ( time() - $this->time);exit(0);}else {$cli->send("Get");}}public function onConnect( $cli) {$cli->send("Get");$this->time = time();}public function onClose( $cli) {echo "Client close connection\n";}public function onError() {}public function send($data) {$this->client->send( $data );}public function isConnected() {return $this->client->isConnected();}
}
$cli = new Client();
$cli->connect();

上面代码略有修改 运行截图如下

server

client

数据库

swoole task MySQL连接池相关推荐

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

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

  2. swoole实现Timer定时器、心跳检测及Task进阶实例:mysql连接池

    2019独角兽企业重金招聘Python工程师标准>>> Table of Contents 1.Timer定时器 2.心跳检测 3.Task进阶:MySQL连接池 环境说明: 系统: ...

  3. swoole mysql 连接数_用swoole简单实现MySQL连接池

    MySQL连接池 在传统的网站开发中,比如LNMP模式,由Nginx的master进程接收请求然后分给多个worker进程,每个worker进程再链接php-fpm的master进程,php-fpm再 ...

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

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

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

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

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

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

  7. mysql多个字符串连接池_使用Coroutine\Channel实现一个简单的MySQL连接池

    Channel通道,类似于go语言的chan,支持多生产者协程和多消费者协程,Swoole底层自动实现了协程的切换和调度 Channel实现原理 通道与PHP的Array类似,仅占用内存,没有其他额外 ...

  8. mysql内连接和外连接的区别_Swoole4创建Mysql连接池

    一 .什么是mysql连接池 场景:每秒同时有1000个并发,但是这个mysql同时只能处理400个连接,mysql会宕机. 解决方案:连接池,这个连接池建立了200个和mysql的连接,这1000个 ...

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

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

最新文章

  1. 50强人工智能面试问题与解答
  2. 【开发技术】视频URL采集
  3. 你不了解PHP的10件事情
  4. WebService学习笔记---CXF入门
  5. 在Ubuntu 18.04系统中使用Netplan工具配置网络
  6. python异步调用_python如何实现异步调用函数执行
  7. null=null不能作为关联条件
  8. android 照片拼接长图_图文长截图(长图拼接制作)
  9. html 滑动条 实时计算,滑动条:拖动滑块改变进度
  10. 信息系统管理师备考指南
  11. 机器学习-累计分布函数(CDF)
  12. c语言json数据解析,C语言库函数解析JSON文件
  13. 第二次团队作业 -- 预则立他山之石
  14. mysql实验视图与索引_视图和索引(数据库实验4)【借鉴实操】
  15. Python基础之Flask快速入门
  16. 微信小程序零基础入门_第一章 小程序和开发者工具的介绍
  17. mac idea 触控板 缩放 字体大小
  18. java计算机毕业设计政府人才机构在线考试系统2021源码+mysql数据库+系统+lw文档+部署
  19. 离散数学第二版计算机系,离散数学 第2版
  20. debian linux 修改时区

热门文章

  1. 吴恩达|机器学习作业目录
  2. 花书+吴恩达深度学习(十)卷积神经网络 CNN 之卷积层
  3. 机器学习-吴恩达-笔记-5-神经网络学习
  4. 总用量的统计_每月公开使用量!广州市开启机制砂信息采集工作
  5. c语言中乱显示数字,同时显示不同的数字
  6. 由于找不到iUtils.dll,无法继续执行代码。重新安装程序可能会解决此问题。
  7. 解决kali-2019.4中文乱码问题
  8. 如何修改layui数据表格绑定的开关事件?
  9. android设置密码框,Android手机卫士之设置密码对话框
  10. Servlet 版本与web.xml配置