Timer毫秒级定时器
1、基于Reactor线程(在Task worker中使用系统定时器)
2、基于epoll的timeout机制实现
Timer使用
swoole_timer_tick(int $ms,mixed $callback,mixed $param=null);
永久级别定时器
swoole_timer_after(int $ms,mixed $callback);
一次性定时器
代码示例
<?php
class Server
{
private $serv;
public $pdo;
public function __construct() {
$this->serv = new swoole_server("0.0.0.0", 9501);
$this->serv->set(array(
'worker_num' => 3,
'task_worker_num'=>3,
'daemonize' => false,
'max_request' => 10000,
'dispatch_mode' => 2,
// 'debug_mode'=> 0,
));
$this->serv->on('Start', array($this, 'onStart'));
$this->serv->on('Connect', array($this, 'onConnect'));
$this->serv->on('Receive', array($this, 'onReceive'));
$this->serv->on('Close', array($this, 'onClose'));
$this->serv->on('WorkerStart', array($this, 'onWorkerStart'));
$this->serv->on('Task',array($this,'onTask'));
$this->serv->on('Finish',array($this,'onFinish'));
$this->serv->start();
}
public function onStart( $serv ) {
echo "Start\n";
}
public function onConnect( $serv, $fd, $from_id ) {
// $serv->send( $fd, "Hello {$fd}!" );
echo "client {$fd} Connect\n";
}
//task回调会在worker进程创建之初调用 不会区分是worker进程还是taskworker进程
public function onWorkerStart($serv,$worker_id)
{
if($worker_id==0){
swoole_timer_tick(1000,function($timer_id,$params){
echo "timer running\n";
echo "recv: {$params}\n";
},'hello');
}
}
//收到客户端的请求
public function onReceive( swoole_server $serv, $fd, $from_id, $data ) {
echo "GET Message From Client {$fd}:{$data}";
swoole_timer_after(1000,function()use($serv,$fd){
echo "timer after\n";
$serv->send($fd,'Hello later\n');
});
echo "Contimue Handler worker\n";
}
public function onTask($serv,$task_id,$from_id,$data)
{
return '完成了';
}
public function onFinish($serv,$task_id,$data){
echo "Task {$task_id} finish\n";
echo "Result:{$data} \n";
}
public function onClose( $serv, $fd, $from_id ) {
echo "Client {$fd} close connection\n";
}
}
// 启动服务器
$server = new Server();
第二重方式服务器端代码
<?php
class Server
{
private $serv;
private $timer_id;
private $test;
public function __construct() {
$this->serv = new swoole_server("0.0.0.0", 9501);
$this->serv->set(array(
'worker_num' => 3,
'task_worker_num'=>3,
'daemonize' => false,
'max_request' => 10000,
'dispatch_mode' => 2,
// 'debug_mode'=> 0,
));
$this->serv->on('Start', array($this, 'onStart'));
$this->serv->on('Connect', array($this, 'onConnect'));
$this->serv->on('Receive', array($this, 'onReceive'));
$this->serv->on('Close', array($this, 'onClose'));
$this->serv->on('WorkerStart', array($this, 'onWorkerStart'));
$this->serv->on('Task',array($this,'onTask'));
$this->serv->on('Finish',array($this,'onFinish'));
$this->serv->start();
}
public function onStart( $serv ) {
echo "Start\n";
}
public function onConnect( $serv, $fd, $from_id ) {
// $serv->send( $fd, "Hello {$fd}!" );
echo "client {$fd} Connect\n";
}
//task回调会在worker进程创建之初调用 不会区分是worker进程还是taskworker进程
public function onWorkerStart($serv,$worker_id)
{
if($worker_id==0){
// swoole_timer_tick(1000,function($timer_id,$params){
// echo "timer running\n";
// echo "recv: {$params}\n";
// },'hello');
$this->test=new test();
$this->test->index=2;
swoole_timer_tick(1000,array($this,'onTick'),'hi~!');
}
}
//收到客户端的请求
public function onReceive( swoole_server $serv, $fd, $from_id, $data ) {
echo "GET Message From Client {$fd}:{$data}";
swoole_timer_after(1000,function()use($serv,$fd){
echo "timer after\n";
$serv->send($fd,'Hello later\n');
});
echo "Contimue Handler worker\n";
}
public function onTask($serv,$task_id,$from_id,$data)
{
return '完成了';
}
public function onFinish($serv,$task_id,$data){
echo "Task {$task_id} finish\n";
echo "Result:{$data} \n";
}
public function onTick($timer_id,$params=null)
{
echo "params: {$params}\n";
echo "Timer {$timer_id} running\n";
echo "timer running\n";
var_dump($this->test);
}
public function onClose( $serv, $fd, $from_id ) {
echo "Client {$fd} close connection\n";
}
}
class test{
public $index=0;
}
// 启动服务器
$server = new Server();
客户端
<?php
class Client
{
private $client;
public function __construct() {
$this->client = new swoole_client(SWOOLE_SOCK_TCP);
}
public function connect() {
if( !$this->client->connect("127.0.0.1", 9501 , 1) ) {
echo "Error:链接失败\n";
}
fwrite(STDOUT, "请输入消息:");
$msg = trim(fgets(STDIN));
$this->client->send( $msg );
sleep(1);
$message = $this->client->recv();
echo "Get Message From Server:{$message}\n";
}
}
$client = new Client();
$client->connect();
timer-常见问题
1、timer传递参数
可以通过tick方法的第三个参数传递,也可以使用use闭包
2、timer传递对象
onTimer是在调用tick 方法的进程中回调、因此可以直接使用的worker进程中声明对象(局部变量无法访问)。
3、Timer的清除
Tick方法会返回timer_id,可以使用swoole_timer_clear清除指定的定时器