一、执行异步任务
在Server程序中如果需要执行很耗时的操作,比如一个聊天服务器发送广播,Web服务器中发送邮件。如果直接去执行这些函数就会阻塞当前进程,导致服务器响应变慢。
Swoole提供了异步任务处理的功能,可以投递一个异步任务到TaskWorker进程池中执行,不影响当前请求的处理速度。
如何使用:
- onTask
- onFinish
- 设置task_worker_num
二、代码实现
我们看Swoole官方文档入门指引->快速起步->Task执行异步任务
我们可以使用上一节我们封装的 websocket
类中使用:
ws_task.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");
}
/**
* 监听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);
$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();
前端静态页面:
ws_task_client.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket TEST</title>
</head>
<body>
<h1>Swoole-TEST</h1>
<script>
var wsUrl = "ws://0.0.0.0:8880";
var websocket = new WebSocket(wsUrl);
// 实例化onopen对象
websocket.onopen = function(evt){
websocket.send("Hello-Lily"); // 发送信息给服务端
console.log("connected-swoole-success")
}
// 实例化 onmessage
websocket.onmessage = function(evt){
console.log("ws-server-return-data"+evt.data)
}
// 实例化 onclose
websocket.onclose = function(evt){
console.log("close")
}
// onerror
websocket.onerror = function (evt) {
console.log("error:" + evt.data)
}
</script>
</body>
</html>
我们在先开启websocket服务:
# php ws_task.php
然后在浏览器运行 ws_task_client.html 页面:
这时我们再看服务端打印:
# php ws_task.php
Open:3
ser-push-message:Hello-Lily
clientid-1 is closed
taskId:0
finish-data-success:on task finish
我们可以看出,页面message及时响应,而在服务器端Task异步任务过了10s才输出来了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。