资讯专栏INFORMATION COLUMN

Swoole笔记(二)

jsummer / 410人阅读

摘要:配置了参数后将会启用功能,务必要注册个事件回调函数。周期性定时器一次性定时器清除定时器定时器回调函数注意最大不得超过。进程中不能添加定时器。建议在回调里写定时器。定时器示例防止重复每隔触发一次后执行此函数

本文示例代码详见:https://github.com/52fhy/swoo...。

重新打开日志

在1.8.11及之后版本支持重新打开日志:向Server主进程发送SIGRTMIN信号。假设主进程id是3427,那么我们可以:

kill -34 3427

注:SIGRTMIN信号的id是34。通过kill -l查看。

那么如何利用这个特征实现每天自动写入新的日志文件里面呢?

假设日志文件是/log/swoole.log,我们可以在每天0点运行shell命令:

mv /log/swoole.log /log/$(date -d "-1 day" +%y-%m-%d).log
kill -34 $(ps aux|grep swoole_task|grep swoole_task_matser|grep -v grep|awk "{print $2}") # 找到主进程,需要提前命名

我们也可以把master进程的PID写入到文件:

$server->set(array(
    "pid_file" => __DIR__."/server.pid",
));

在Server关闭时自动删除PID文件。此选项在1.9.5或更高版本可用。

信号管理

Swoole支持的信号:

SIGKILL -9 pid 强制杀掉进程
SIGUSR1 -10 master_pid 重启所有worker进程
SIGUSR2 -12 master_pid 重启所有task_worker进程
SIGRTMIN -34 master_pid 重新打开日志(版本1.8.11+)

master_pid代表主进程pid。示例(假设主进程名称是swoole_server,pid是3427):

# 杀掉进程swoole_server
kill -9 $(ps aux|grep swoole_server|grep -v grep|awk "{print $2}")

# 重启swoole_server的worker进程
kill -10 $(ps aux|grep swoole_server|grep -v grep|awk "{print $2}")

# 重新打开日志
kill -34 3427
Task

我们可以在worker进程中投递一个异步任务到task_worker池中。此函数是非阻塞的,执行完毕会立即返回。worker进程可以继续处理新的请求。

通常会把耗时的任务交给task_worker来处理。

我们可以通过如下代码判断是Worker进程还是TaskWorker进程:

function onWorkerStart($serv, $worker_id) {
    if ($worker_id >= $serv->setting["worker_num"]) {  //超过worker_num,表示这是一个task进程

    }
}

看一个示例:

set(array(
    "daemonize" => false,
    "reactor_num" => 2,
    "worker_num" => 1,
    "task_worker_num" => 1,
));

$server->on("start", function ($serv){ 
    swoole_set_process_name("swoole_task_matser"); //主进程命名
});

$server->on("connect", function ($serv, $fd){ 
    echo "client connect. fd is {$fd}
";
});

$server->on("receive", function ($serv, $fd, $from_id, $data){
    
    echo sprintf("onReceive. fd: %d , data: %s
", $fd, json_encode($data) );
    
    $serv->task(json_encode([
        "fd" => $fd,
        "task_name" => "send_email",
        "email_content" => $data,
        "email" => "admin@qq.com"
    ]));
});

$server->on("close", function ($serv, $fd){
    echo "client close. fd is {$fd}
";
});

$server->on("task", function (swoole_server $serv, $task_id, $from_id,  $data){
    echo $data;
    
    $data = json_decode($data, true);
    $serv->send($data["fd"], "send eamil to {$data["email"]}, content is : {$data["email_content"]}
");
    
    //echo "task finished";
    //return "task finished";
    $serv->finish("task finished");
});

$server->on("finish", function (swoole_server $serv, $task_id, $data){
    echo "onFinish:" .$data;
});

$server -> start();

这里新建了一个tcp服务器,参数里设置worker_num进程为1,task_worker_num为1。

配置了task_worker_num参数后将会启用task功能,swoole_server务必要注册onTask/onFinish2个事件回调函数。如果没有注册,服务器程序将无法启动。

onTask回调接收4个参数,分别是serv对象、任务ID、自于哪个worker进程、任务的内容。注意的是,$data必须是字符串。我们可以在worker进程里使用`swoole_server->task
($data)`进行任务投递。

onFinish回调用于将处理结果告知worker进程,此回调必须有,但是否被调用由OnTask决定。在OnTask里使用return或者finish()可以将处理结果发生到onFinish回调,否则onFinish回调是不会被调用的。也就是说:finish()是可选的。如果worker进程不关心任务执行的结果,不需要调用此函数。onFinish回调里的$data同样必须是字符串。

我们新起一个窗口,使用telnet发送消息到服务端进行测试:
client端:

telnet 127.0.0.1 8088
Trying 127.0.0.1...
Connected to 127.0.0.1.

hhh
send eamil to admin@qq.com, content is : hhh

server端:

client connect. fd is 1
onReceive. fd: 1 , data: "hhh
"
{"fd":1,"task_name":"send_email","email_content":"hhh
","email":"admin@qq.com"}
onFinish:task finished

onFinish回调里不使用return或者finish(),我们将看不到server端最后一行输出。

此时服务器进程模型:

pstree -ap | grep swoole
  |   |       `-php,3190 swoole_task.php
  |   |           |-php,3192 swoole_task.php
  |   |           |   |-php,3194 swoole_task.php
  |   |           |   `-php,3195 swoole_task.php

看到两个worker进程,其中一个是worker进程,另外一个是task_worker进程。

定时器

Swoole提供强大的异步毫秒定时器,基于timerfd+epoll实现。主要方法:
1、swoole_timer_tick:周期性定时器,类似于JavaScript里的setInterval()
2、swoole_timer_after:一次性定时器。
3、swoole_timer_clear:清除定时器。

# 周期性定时器
int swoole_timer_tick(int $ms, callable $callback, mixed $user_param);

# 一次性定时器
swoole_timer_after(int $after_time_ms, mixed $callback_function, mixed $user_param);

# 清除定时器
bool swoole_timer_clear(int $timer_id)

# 定时器回调函数
function callbackFunction(int $timer_id, mixed $params = null);

注意:

$ms 最大不得超过 86400000。

manager进程中不能添加定时器。

建议在WorkerStart回调里写定时器。

定时器示例:

$server->on("WorkerStart", function (swoole_server $server, $worker_id){
    if ($server->worker_id == 0){//防止重复
        //每隔2000ms触发一次
        swoole_timer_tick(2000, function ($timer_id) {
            echo "tick-2000ms
";
        });
        
        //3000ms后执行此函数
        swoole_timer_after(3000, function () {
            echo "after 3000ms.
";
        });
    }
});

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/23062.html

相关文章

  • PHP多进程系列笔记(五)

    摘要:消息队列更常见的用途是主进程分配任务,子进程消费执行。子进程前面加了个,这是为了防止父进程还未往消息队列中加入内容直接退出。 前面几节都是讲解pcntl扩展实现的多进程程序。本节给大家介绍swoole扩展的swoole_process模块。 swoole多进程 swoole_process 是swoole提供的进程管理模块,用来替代PHP的pcntl扩展。 首先,确保安装的swoole...

    qianfeng 评论0 收藏0
  • swoole 学习笔记swoole 真的优秀一个框架

    摘要:所以,我感觉学习,需要一个引导。学习参考链接喵星球特别厉害的一个官网的几个框架文档优势先看一下的结构设计的应用场景的设计项目中引入一个简易的具体参考一篇文章,集合和的简易实例项目中引入结合致敬 前期学完了操作系统,特别是知道了进程,线程 调度的问题。回来看,发现了很多细节。第三次看文档,最初经一个高手朋友的介绍,看swoole,说文档写的贼好。但是看的时候,也是很一头雾水,只知道把de...

    13651657101 评论0 收藏0
  • Swoole笔记(一)

    摘要:修复添加超过万个以上定时器时发生崩溃的问题增加模块,下高性能序列化库修复监听端口设置无效的问题等。线程来处理网络事件轮询,读取数据。当的三次握手成功了以后,由这个线程将连接成功的消息告诉进程,再由进程转交给进程。此时进程触发事件。 本文示例代码详见:https://github.com/52fhy/swoo...。 简介 Swoole是一个PHP扩展,提供了PHP语言的异步多线程服务器...

    SHERlocked93 评论0 收藏0
  • swoole 学习笔记

    摘要:安装准备或更高版本或更高版本安装扩展配置支持编辑在其中加入扩展支持服务端代码服务端客户端代码测试代码在命令模式下输入重新再开一个窗口可以用检测如服务端客户端如上,表示服务端启动,客户端连接服务端返回消息,一个闭环形成开发者头条 1.安装准备 php-5.3.10 // 或更高版本 gcc-4.4 //或更高版本 make autoconf 2.安装swoole扩展 w...

    justCoding 评论0 收藏0
  • Swoole笔记(四)

    摘要:配合模块,创建的子进程可以异步的事件驱动模式。默认为阻塞读取。函数用于将一个加入到的事件监听中。为事件类型的掩码,可选择关闭开启可读可写事件,如,,或者。在程序中使用,可以理解为在进程中将此注册到事件中。 Process Process是swoole内置的进程管理模块,用来替代PHP的pcntl扩展。 swoole_process支持重定向标准输入和输出,在子进程内echo不会打印屏...

    yzd 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<