欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

PHP高性能I/O框架Libevent的使用详解

程序员文章站 2022-10-28 13:07:39
libevent 是一个用c语言编写的、轻量级的开源高性能i/o框架,支持多种 i/o 多路复用技术: epoll、 poll、 dev/poll、 select 和 kqueue 等;支持 i/o...

libevent 是一个用c语言编写的、轻量级的开源高性能i/o框架,支持多种 i/o 多路复用技术: epoll、 poll、 dev/poll、 select 和 kqueue 等;支持 i/o,定时器和信号等事件;注册事件优先级。php提供了对应的扩展libevent、event。

libevent扩展很久没有更新了,仅支持php5系列,php7虽然有网友fork了 libevent 扩展的进行更新兼容,但是稳定性不好,可能会出现段错误,所以php7最好使用 event 扩展。

与libevent扩展不同的是,event 扩展提供了面向对象的接口,且支持更多特性。

libevent扩展

需要先安装 libevent 库:

yum install libevent-dev

然后安装php扩展。

php5安装:

pecl install libevent-0.1.0

php7安装(不稳定):

git clone https://github.com/expressif/pecl-event-libevent.git
cd pecl-event-libevent
phpize
./configure
make && sudo make install

注:后面的代码示例均使用的php5.6+libevent-0.1.0环境。

基本使用

下面的例子实现了一个单进程的tcp server,基于libevent实现i/o复用,达到高性能。

libevent_tcp_server.php


我们先运行代码:

$ php libevent_tcp_server.php
waiting client...
start run...

客户端使用telnet:

$ telnet 127.0.0.1 9201
trying 127.0.0.1...
connected to 127.0.0.1.
escape character is '^]'.
hello server!

代码里面我加了很多注释,基本上能看明白。需要注意的是:

1、event_base是全局的,只需要创建一次,后续都是event的设置和添加。

2、event_set的回调函数有三个参数,分别是$fd,$events,$arg。也就是 event_set 函数的$fd,$events,$arg参数。arg 如果需要多个,可以为数组。fd参数实际是保存的客户端连接,是个resource。events参数支持下列这些常量:

ev_timeout: 超时。利用事件可以实现定时器

ev_read: 只要网络缓冲中还有数据,回调函数就会被触发

ev_write: 只要塞给网络缓冲的数据被写完,回调函数就会被触发

ev_signal: posix信号量

ev_persist: 不指定这个属性的话,回调函数被触发后事件会被删除

ev_et: edge-trigger边缘触发

使用event_buffer

libevent还提供了event_buffer_系列函数。手册里的解释是:libevent在基础的api里提供了一层抽象层,使用 buffered event ,我们无序手动处理i/o。估计是对性能的提升。

示例:

libevent_buffer_tcp_server.php


注释我都写了,相比前一个例字,主要有3个地方不同:

1、ev_accept里设置read事件全换成了待buffer的函数;

2、ev_read回调接收参数为2个;

3、ev_read回调里读取消息使用event_buffer_read,而不是fread。另外增加了ev_write,ev_error回调。

定时器

libevent提供了event_timer_*系列函数,实现一次性定时器,精度微秒。

libevent_timer.php

 5){
  event_timer_del($args[1]); //删除定时器
 }
}

$base = event_base_new();
$ev_timer = event_timer_new();
event_timer_set($ev_timer, 'ev_timer', [$time_intval, $ev_timer]);
event_base_set($ev_timer, $base);
event_timer_add($ev_timer, $time_intval);//单位微秒

event_base_loop($base);

上面的例子实现了每1秒执行一次回调函数。

使用event_*系列函数也可以实现:
libevent_timer2.php

 5){
  event_timer_del($args[1]);
 }
}

$base = event_base_new();
$event = event_new();
event_set($event, 0, ev_timeout, 'ev_timer', [$time_intval, $event]);
event_base_set($event, $base);
event_add($event, $time_intval);

event_base_loop($base);

可以看出,event_timer_*系列函数是对event_*系列函数ev_timeout事件的包装。

总结

event_*系列函数基本上可以分为上面三大类。还有几个函数没有提到,大家看手册就能了解。