学习这件事不在乎有没有人教你,最重要的是在于你自己有没有觉悟和恒心。————法布尔

编程

高性能IO框架libevent读书笔记记录

  • 2020-02-27 12:53
简介 :《Linux高性能服务器编程》一书中第12章节内容, 这本书读了三遍, 像我这种非计算机出身的人,真的得一遍遍的理解, 记个笔记,写个demo玩玩. 细水长流~~

概念

要写一个服务器程序一般需要实现三个事件: 信号 , I/O逻辑 , 定时事件 . 要处理这三个事件一般需要考虑三个问题: 统一事件源(好管理) , 可移植性(跨系统支持) , 对并发编程的支持(多个客户端同时请求) , 开源(感谢开源)I/O框架libevent已经实现了对这三个事件的封装,并且提供了简单的接口.

为啥要用这个库写服务器程序?

网上找了个代码例子总结波:

架构一:

  • // 阻塞模式
  • $socket = stream_socket_server("0.0.0.0:9600", $errno, $errstr);
  • if (!$socket) {
  • echo "$errstr ($errno)";
  • } else {
  • while (true) {
  • $conn = @stream_socket_accept($socket);
  • if ($conn)
  • {
  • fwrite($conn, $data);
  • fclose($conn);
  • } else {
  • echo "no newSocket\n";
  • }
  • }
  • }
  • 缺点:这种服务器架构是阻塞模式,他是一个处理完才接着下一个,不符合并发请求,要是请求的人多了,那就卡死了。处理任务串行化。

架构二:

  • // 使用多进程方式
  • $socket = stream_socket_server("0.0.0.0:9600", $errno, $errstr);
  • if (!$socket) {
  • echo "$errstr ($errno)";
  • } else {
  • while (true) {
  • if (pcntl_fork() == 0)
  • {
  • $conn = @stream_socket_accept($socket);
  • if ($conn)
  • {
  • fwrite($conn, $data);
  • fclose($conn);
  • } else {
  • echo "no newSocket\n";
  • }
  • }
  • }
  • }
  • 缺点: 这种服务器架构虽然支持了并发,但是进程开销很大,每次接收到链接我就fork个进程,如果请求的人多了,进程开销,进程切换,内存,服务器压力比较大

服务器基于libevent库需要实现的基本点

句柄handle

I/O框架库要处理的对象, 即I/O事件,信号,定时事件,统一称为事件源 , 一个事件源通常和一个句柄绑定在一起,句柄的作用就是,当内核检测到就绪事件的时候,它将通知应用程序这一事件.Linux句柄通常是文件描述符.定时事件一般对应的就是信号值(后面代码注释备注了波)

事件多路分发器

事件的到来是随机的,异步的,我们无法预知程序何时收到一个客户连接请求,又亦或收到一个暂停信号, 所以程序需要循环的等待并处理事件, 这就是事件循环,在事件循环中,等待事件一般使用I/O复用技术来实现, I/O框架库一般将系统支持的各种I/O复用系统调用封装成容易的接口,称为事件多路分发器.其内部调用的是select,poll,epoll_wait(这些在第九章I/O复用章节,就简单了解了下不会写哈哈哈)等函数.

事件处理器和具体事件处理器

事件处理器执行事件对应的业务逻辑 , 它通常包含一个或多个handle_event 回调函数,这些回调函数在事件循环中被执行.

程序代码大概流程

一. 创建event_base对象, 一个event_base 对象就是相当于一个Reactor实例(负责响应IO事件,当检测到一个新的事件,将其发送给相应的Handler去处理,配合多进程是否就是进程池了?).

二. 创建具体的事件处理器(加入到事件队列),并设置他们所从属的Reactor实例,add事件函数有个fd参数,这个fd参数就是设置与该事件处理器关联的句柄 : 创建I/O事件处理器fd参数传递文件描述符 , 创建信号事件那fd就是信号值 , 处理定时事件那fd就传个-1

三. 进入事件循环.

PHP基于event扩展的代码例子

待会写

Top