使用 libevent 和 libev 提高网络应用性能的方法

2019-10-15 12:25:53刘景俊

accept_callback():当接受连接时,事件系统调用此函数。此函数接受到客户端的连接;添加客户端套接字信息和一个 bufferevent 结构;在事件结构中为客户端套接字上的读/写/错误事件添加回调函数;作为参数传递客户端结构(和嵌入的 eventbuffer 和客户端套接字)。每当对应的客户端套接字包含读、写或错误操作时,调用对应的回调函数。
buf_read_callback():当客户端套接字有要读的数据时调用它。作为回显服务,此函数把 "you said..." 写回客户端。套接字仍然打开,可以接受新请求。
buf_write_callback():当有要写的数据时调用它。在这个简单的服务中,不需要此函数,所以定义是空的。
buf_error_callback():当出现错误时调用它。这包括客户端中断连接。在出现错误的所有场景中,关闭客户端套接字,从事件列表中删除客户端套接字的事件条目,释放客户端结构的内存。
setnonblock():设置网络套接字以开放 I/O。
当客户端连接时,在事件队列中添加新事件以处理客户端连接;当客户端中断连接时删除事件。在幕后,libevent 处理网络套接字,识别需要服务的客户端,分别调用对应的函数。

为了构建这个应用程序,需要编译 C 源代码并添加 libevent 库:$ gcc -o basic basic.c -levent。

从客户端的角度来看,这个服务器仅仅把发送给它的任何文本发送回来(见 清单 3)。


清单 3. 服务器把发送给它的文本发送回来

$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello!
You said Hello!

这样的网络应用程序非常适合需要处理多个连接的大规模分布式部署,比如 IBM Cloud 系统。

很难通过简单的解决方案观察处理大量并发连接的情况和性能改进。可以使用嵌入的 HTTP 实现帮助了解可伸缩性。

使用内置的 HTTP 服务器

如果希望构建本机应用程序,可以使用一般的基于网络的 libevent 接口;但是,越来越常见的场景是开发基于 HTTP 协议的应用程序,以及装载或动态地重新装载信息的网页。如果使用任何 AJAX 库,客户端就需要 HTTP,即使您返回的信息是 XML 或 JSON。

libevent 中的 HTTP 实现并不是 Apache HTTP 服务器的替代品,而是适用于与云和 web 环境相关联的大规模动态内容的实用解决方案。例如,可以在 IBM Cloud 或其他解决方案中部署基于 libevent 的接口。因为可以使用 HTTP 进行通信,服务器可以与其他组件集成。

要想使用 libevent 服务,需要使用与主要网络事件模型相同的基本结构,但是还必须处理网络接口,HTTP 包装器会替您处理。这使整个过程变成四个函数调用(初始化、启动 HTTP 服务器、设置 HTTP 回调函数和进入事件循环),再加上发送回数据的回调函数。清单 4 给出一个非常简单的示例: