Swoole入门篇(下)

上一篇我们讲了如何安装Swoole扩展,编写HTTP服务器,编写WebSocket服务器。这一章将会介绍Task异步任务机制,以及Timer定时器功能。

Task异步任务

Swoole Task:wiki.swoole.com/wiki/page/1…

为什么需要异步任务这种机制呢?

因为在某些场景之下,客户端是不需要关心服务器处理逻辑的,更需要的是实时的响应。比如一个实时的联机游戏,将游戏数据保存到MySQL中就是一个耗时的操作,客户端并不需要知道保存的结果,需要的仅仅是游戏的数据。

如果按照普通的PHP Web开发,每次请求的代码逻辑都是同步完成再进行响应,那游戏的延迟就会高到无法正常游玩。这时候就需要使用Task这种异步任务的方式,让数据保存这种耗时任务交由另一个进程进行处理,服务端就能够立马响应客户端。

Task初始化

使用Task需要在Server创建的时候设置task_worker_num属性,并且绑定onTask()onFinish()方法。

做题时间

  1. 根据官方文档,在上一章的WebSocket Server代码的基础上,初始化Task机制。

    <?php … class WebSocketServer {

    1. ...
    2. public function __construct()
    3. {
    4. ...
    5. $this->server->set(array(
    6. 'worker_num' => 4,
    7. 'task_worker_num' => 4,
    8. ));
    9. ...
    10. $this->server->on('task', [$this, 'onTask']);
    11. $this->server->on('finish', [$this, 'onFinish']);
    12. ...
    13. }
    14. ...
    15. public function onMessage($server, $request)
    16. {
    17. ...
    18. $server->task('task_test');
    19. }
    20. ...
    21. public function onTask($server, $taskId, $srcWorkerId, $data)
    22. {
    23. echo "Tasker进程接收到数据" . PHP_EOL;
    24. $i = 5;
    25. while ($i--) {
    26. sleep(1);
    27. echo date('H:i:s') . PHP_EOL;
    28. }
    29. $server->finish($data);
    30. }
    31. public function onFinish($server, $taskId, $data)
    32. {
    33. echo "Task#$taskId finished, data_len=" . strlen($data) . PHP_EOL;
    34. }

    } …

代码的逻辑很简单,设置task_worker4个,当onMessage()方法接收到消息后,投递一个task任务并传入数据task_test字符串。投递后将会触发Task Worker回调onTask()方法,在参数中会接收到$server对象投递的task_test字符串,连续5秒每秒会打印一次当前时间戳。当打印完毕后,调用$server对象的finish()方法,将数据返回到发起投递任务的主线程worker

打开chrome开发者工具,查看network标签。

19 Swoole入门篇(下) - 图1

这里显示了我们的服务端返回数据时间为23:48:10,接下来查看我们的服务端输出。

  1. server: handshake success with fd1
  2. receive from 1:this is client,opcode:1,fin:1
  3. Tasker进程接收到数据
  4. 23:48:11
  5. 23:48:12
  6. 23:48:13
  7. 23:48:14
  8. 23:48:15
  9. Task#0 finished, data_len=9

可以看到,onTask()方法输出的时间是从23:48:11开始的,当输出完5次后,触发onFinish()方法输出了data_len。也就是说我们的Task机制运行正常。

Timer定时器

Swoole Timer:wiki.swoole.com/wiki/page/4…

Swoole框架为我们提供了两种定时器:循环定时器swoole_timer_tick和一次性定时器swoole_timer_after,基本能够满足大部分场景。

swoole_timer_tick

swoole_timer_tick是循环定时器,会按照设置的间隔时间一直重复的调用回调函数。在某些游戏中,可以使用这个定时器一直进行快速循环计算,将最新的游戏数据发送给每一个客户端。

新建一个test.php文件,在里面输入以下代码:

  1. <?php
  2. //每隔2000ms触发一次
  3. swoole_timer_tick(2000, function ($timer_id) {
  4. echo time() . PHP_EOL;
  5. });

运行效果:

  1. [root@localhost PHPDemo]# php test.php
  2. 1560955350
  3. 1560955352
  4. 1560955354
  5. 1560955356
  6. ...

程序将会每隔两秒进行一次输出。

swoole_timer_after

swoole_timer_after是一次性定时器,会进行等待设定好的时间间隔,触发一次回调函数。在某些游戏中,可以使用这个定时器做到游戏单局时长限制,触发定时器来结束一局游戏。

test.php文件中输入以下代码:

  1. <?php
  2. //3000ms后执行此函数
  3. swoole_timer_after(3000, function () {
  4. echo "after 3000ms.\n";
  5. });

运行效果:

  1. [root@localhost PHPDemo]# php test.php
  2. after 3000ms.
  3. [root@localhost PHPDemo]#

程序会在3秒后进行一次输出操作。

小结

Swoole入门篇到这里就结束了,篇幅较少是因为小册目前只使用了这些技术,看上去也不是太难对吧?Swoole还有许多例如协程异步MySQL异步Redis等技术等着你去学习。

仅仅学习入门篇的Demo写法是远远不够的,只有做项目写代码才能更深入的理解技术的使用方法,更多关于Swoole的内容就请童鞋们在游戏开发篇章中进行学习了。