2019独角兽企业重金招聘Python工程师标准>>>

Table of Contents

  • 1.Timer定时器
  • 2.心跳检测
  • 3.Task进阶:MySQL连接池

环境说明: 系统:Ubuntu14.04 (安装教程包括CentOS6.5)
PHP版本:PHP-5.5.10
swoole版本:1.7.7-stable

1.Timer定时器

在实际应用中,往往会遇到需要每隔一段时间重复做一件事,比如心跳检测、订阅消息、数据库备份等工作。通常,我们会借助PHP的time()以及相关函数自己实现一个定时器,或者使用crontab工具来实现。但是,自定义的定时器容易出错,而使用crontab则需要编写额外的脚本文件,无论是迁移还是调试都比较麻烦。
因此,Swoole提供了一个内置的Timer定时器功能,通过函数addtimer即可在Swoole中添加一个定时器,该定时器会在建立之后,按照预先设定好的时间间隔,每到对应的时间就会调用一次回调函数onTimer通知Server。
简单示例如下:

$this->serv->on('Timer', array($this, 'onTimer'));public function onWorkerStart( $serv , $worker_id) {// 在Worker进程开启时绑定定时器// 只有当worker_id为0时才添加定时器,避免重复添加if( $worker_id == 0 ) {$serv->addtimer(500);$serv->addtimer(1000);$serv->addtimer(1500);}}public function onTimer($serv, $interval) {switch( $interval ) {case 500: { // echo "Do Thing A at interval 500\n";break;}case 1000:{echo "Do Thing B at interval 1000\n";break;}case 1500:{echo "Do Thing C at interval 1500\n";break;}}}

可以看到,在onWorkerStart回调函数中,通过addtimer添加了三个定时器,时间间隔分别为500、1000、1500。而在onTimer回调中,正好通过间隔的不同来区分不同的定时器回调,从而执行不同的操作。
需要注意的是,在上述示例中,当1000ms的定时器被触发时,500ms的定时器同样会被触发,但是不能保证会在1000ms定时器前触发还是后触发,因此需要注意,定时器中的操作不能依赖其他定时器的执行结果。

点此查看完整示例

(PS:在Swoole-1.7.7版本,新提供了一个after函数, 这个功能的用法会在以后的教程中给出。)

2.心跳检测

上文提到过,使用Timer定时器功能可以实现发送心跳包的功能。事实上,Swoole已经内置了心跳检测功能,能自动close掉长时间没有数据来往的连接。而开启心跳检测功能,只需要设置heartbeat_check_interval和heartbeat_idle_time即可。如下:

$this->serv->set(array('heartbeat_check_interval' => 60,'heartbeat_idle_time' => 600,)
);

其中heartbeat_idle_time的默认值是heartbeat_check_interval的两倍。 在设置这两个选项后,swoole会在内部启动一个线程,每隔heartbeat_check_interval秒后遍历一次全部连接,检查最近一次发送数据的时间和当前时间的差,如果这个差值大于heartbeat_idle_time,则会强制关闭这个连接,并通过回调onClose通知Server进程。 点此查看完整示例 小技巧: 结合之前的Timer功能,如果我们想维持连接,就设置一个略小于如果这个差值大于heartbeat_idle_time的定时器,在定时器内向所有连接发送一个心跳包。如果收到心跳回应,则判断连接正常,如果没有收到,则关闭这个连接或者再次尝试发送。

3.Task进阶:MySQL连接池

上一章中我简单讲解了如何开启和使用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。
(客户端会在每次收到前一个请求的结果后才会发起下一次请求,而不是并发)。

点此查看完整服务端代码
点此查看完整客户端代码

4.Task实战:yii中应用task

在YII框架中结合了swoole 的task 做了异步处理。 本例中 主要用到 1、protected/commands/ServerCommand.php 用来做server。 2、protected/event/下的文件 这里是在异步中的具体实现。

客户端调用参照 TestController

<?php
class TestController extends Controller{public function actionTT(){$message['uid'] = 2;$message['email'] = '83212019@qq.com';$message['title'] = '接口报警邮件';$message['contents'] = "'EmailEvent'接口请求过程出错! 错误信息如下:err_no:'00000' err_msg:'测试队列' 请求参数为:'[]'";$message['type'] = 2;$data['param'] = $message;$data['class'] = 'Email';$client = new EventClient();$data = $client->send($data);}
}
?>

有个task表是用来记录异步任务的。如果失败重试3次。sql在protected/data/sql.sql里。
点此查看完整客户端代码

下章预告:Swoole多端口监听、热重启以及Timer进阶:简单crontab

转载于:https://my.oschina.net/u/1762916/blog/777550

swoole实现Timer定时器、心跳检测及Task进阶实例:mysql连接池相关推荐

  1. swoole task MySQL连接池

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. swoole 服务端heartbeat_check_interval心跳检测 客户端 swoole_timer_tick 发送心跳包 这里只是个demo参考

    服务端 <?php class TimerServer {private $serv;public function __construct() {$this->serv = new sw ...

  9. swoole 连接mysql_swoole教程:用swoole4操作mysql连接池之读写分离

    为什么要读写分离? 一般的系统都是读多写少,利用读写分离,可以提升mysql的效率 读写分离后,从库可以水平扩展 下面我们开始代码之旅吧 配置先改造: $config = [ 'host'=> ...

最新文章

  1. 【直播】张晋:心跳信号分类模型融合
  2. AI 复活「她」! GPT-3 帮美国小哥复刻逝去未婚妻,但又夺走她……
  3. error: C3861: “pcap_open”: 找不到标识符
  4. vi和vim命令行编辑器命令
  5. Modbus通信协议之CRC16冗余循环校验函数
  6. predis操作大全
  7. PHP学习8——图像处理
  8. C++ begin( ) cbegin( ) end() cend()区别
  9. 计算机相关技能简历,简历计算机技能有哪些
  10. 从外观上如何识别单模和多模光纤
  11. 自学测试入门—用户注册功能的测试
  12. 川教版八年级计算机教学计划,川教版八年级下信息技术教学计划.doc
  13. 北京理工大学汇编语言复习重点(可打印)
  14. 利用计算机引号作用,引号有什么作用
  15. Object-Oriented Design Heuristics (zz)
  16. 0.2度背后的美国抉择:压不住新能源
  17. R语言使用lm函数构建分层线性回归模型(添加分组变量构建分层线性回归模型)、使用coef函数提取分层线性回归模型的系数及截距、计算第一个分组的间距和斜率信息(第一个分组,对照组)
  18. python实现图片批量重命名
  19. Windows电脑键盘快捷键大全【最全的快捷键】
  20. MATLAB基本语法详解

热门文章

  1. Spring启动NoClassDefFoundError中EmbeddedValueResolver错误
  2. Centos7 安装 Kubernetes dashboard (安装篇)
  3. 微信小程序wx.request请求服务器json数据并渲染到页面
  4. Linux下iptables 禁止端口和开放端口
  5. Track and Follow an Object----4
  6. 让你的代码量减少3倍!使用kotlin开发Android(四) kotlin bean背后的秘密
  7. Cocos2d入门--2-- 三角函数的应用
  8. Android 插件化 动态升级
  9. silverlight学习笔记(一)—— 使用blend实现缩小Listbox或Scrollviewer中的滚动条
  10. pl/sql 中变量定义范围的小例子: