一、设置定时器
我们一般处理比较常规的定时任务都会用 Linux 系统自带的定时器 crontab 来执行,但是有时候会满足不了我们的业务需求,达不到毫秒级别,不过Swoole可以帮我们实现。
我们看Swoole官方文档入门指引->快速起步->设置定时器
swoole提供了类似JavaScript的setInterval/setTimeout异步高精度定时器,粒度为毫秒级。使用也非常简单。
-
swoole_timer_tick
函数就相当于setInterval,是持续触发的 -
swoole_timer_after
函数相当于setTimeout,仅在约定的时间触发一次 -
swoole_timer_tick
和swoole_timer_after
函数会返回一个整数,表示定时器的ID
可以使用 swoole_timer_clear 清除此定时器,参数为定时器ID
二、代码实现
ws_timer.php
<?php
/**
* WS 优化基础类库
*/
class Ws
{
public $ws = null;
CONST HOST = "0.0.0.0";
CONST PORT = 80;
public function __construct()
{
// static::HOST, static::PORT
$this->ws = new swoole_websocket_server("0.0.0.0", 80);
$this->ws->set(
[
'enable_static_handler' => true, // 静态资源相关设置
'document_root' => "/work/study/code/swoole/demo/static", // 存放静态资源路径
// 'worker_num' => 2,
// 'task_worker_num' => 2,
]
);
$this->ws->on("open", [$this, "onOpen"]);
$this->ws->on("message", [$this, "onMessage"]);
// $this->ws->on("task", [$this, "onTask"]);
// $this->ws->on("finish", [$this, "onFinish"]);
$this->ws->on("close", [$this, "onClose"]);
$this->ws->start();
}
/**
* 监听ws连接事件
* @param $ws
* @param $request
*/
public function onOpen($ws, $request)
{
print_r("Open:" . $request->fd ."\n");
// 使用定时任务
if($request->fd == 1)
{
// 每2秒执行
swoole_timer_tick(2000, function($timer_id){
echo "2s:timerId:{$timer_id}";
});
}
}
/**
* 监听ws连接消息
* @param $ws
* @param $frame
*/
public function onMessage($ws, $frame)
{
echo "ser-push-message:{$frame->data}\n";
// TODO::加入我们这个业务需要执行超过 10s,所以,这里可以使用task异步来处理
$data = [
'task' => 1,
'fd' => $frame->fd,
];
// 投递一个任务
// $ws->task($data);
// 定时任务,5s后执行,这里是异步任务,不会阻塞,这里使用闭包
swoole_timer_after(5000, function() use ($ws, $frame){
echo "5s-after\n";
$ws->push($frame->fd, "server-time-after");
});
$ws->push($frame->fd, "server-push:".date("Y-m-d H:i:s"));
}
/**
* 投递任务
*
* @param $serv
* @param $taskId
* @param $workerId
* @param $data
*/
public function onTask($serv, $task_id, $from_id, $data)
{
// 耗时场景 10s
sleep(10);
return "on task finish"; // 告诉worker
}
public function onFinish($serv, $task_id, $data)
{
echo "taskId:{$task_id}\n";
// 注意:此$data参数为onTask方法返回的结果:on task finish,而不是onTask方法的参数。
echo "finish-data-success:{$data}\n";
}
/**
* 监听WebSocket连接关闭事件
*
* @param $ws
* @param $fd
*/
public function onClose($ws, $fd)
{
echo "clientid-{$fd} is closed \n";
}
}
$ws_obj = new Ws();
在服务器端执行该脚本:
root@5ee6bfcc1310:/work/study/code/swoole/demo/server# php ws_timer.php
Open:3
ser-push-message:Hello-Lily
clientid-1 is closed
5s-after
clientid-2 is closed
在浏览器执行客户端代码:ws_task_client.html
我们可以看到,打开浏览器后,等5秒后,服务器通过定时任务会将 server-time-after
信息推到客户端。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。