基于libevent的多线程http服务器
基于libevent的多线程http server
项目中的业务需要实现最基本的HTTP/1.0版本的web服务器,客户端能够使用GET、POST方法请求资源,项目是运行在嵌入式linux系统中的,并且某一时刻可能有大量并发请求,综合考虑,选择libevent实现一个多线程的http服务器。
本文使用的libevent的版本是libevent-2.1.12-stable。也是目前最新的稳定版本。
程序源代码可以见公众号 xutopia77 文章 基于libevent的多线程http服务器
在开始论述之前,我希望读者对IO多路复用器(尤其是epoll),以及对reactor和proactor模式有个大致的理解。对于这两个方面,网络上已经有大量的文章了,我自己也写过很多,如果读者想要了解这两项内容,可以点击下面链接查阅: select,poll,epoll的区别以及使用方法。
首先,libevent是什么,我们看下官方的介绍:
The libevent API provides a mechanism to execute a callback function when a specific event occurs on a file descriptor or after a timeout has been reached. Furthermore, libevent also support callbacks due to signals or regular timeouts.
libevent API提供了一种机制,可以在文件描述符上发生特定事件或超时后执行回调函数。此外,libevent还支持由于信号或常规超时而产生的回调。
同时看一下百度百科对他的介绍
Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大;源代码相当精炼、易读;跨平台,支持 Windows、 Linux、 *BSD 和 Mac Os;支持多种 I/O 多路复用技术, epoll、 poll、 dev/poll、 select 和 kqueue 等;支持 I/O,定时器和信号等事件;注册事件优先级。
Libevent 已经被广泛的应用,作为底层的网络库;比如 memcached、 Vomit、 Nylon、 Netchat等等。
简单的来讲,libevent是一个网络库,能够帮我们处理大量的网络编程细节,降低我们的网络编程门槛,并且它具备良好的跨平台能力。使用者只需要向它注册一些事件,它就会在合适的时机(比如可读、可写或定时事件触发时)调用我们对应的注册函数。
libevent包括事件管理、缓存管理、DNS、HTTP、缓存事件几大部分。事件管理包括各种IO(socket)、定时器、信号等事件;缓存管理是指evbuffer功能;DNS是libevent提供的一个异步DNS查询功能;
我们要实现http服务器,就是使用他的HTTP组件。HTTP是libevent的一个轻量级http实现,包括服务器和客户端。libevent也支持ssl,这对于有安全需求的网络程序非常的重要,但是其支持不是很完善,比如http server的实现就不支持ssl。
基于libevnet的单线程的使用方法见文章:
这里基于libevnet实现多线程的http服务器。
libevent的多线程使用注意事项:
对于libevnet是否支持多线程,很多资料都有争议,有的说支持,有的说不支持。对于多线程这个特性是否能够使用,只能说多线程多线程是怎么使用的,是怎么与libevent结合的。
1,对于不同的线程,使用不同的base,是可以的。
2,libevent的信号事件是不支持多线程的,因为里面使用了全局变量。
3,不同的线程使用相同的base,即在不同线程里的事件都注册到一个base上,这是不行的,即使加锁也不行,因为某个事件没有用event_set()设置为EV_PERSIST,当事件发生时,会被自动删除。有可能线程a在删除事件的时候,线程b却在添加事件,这样还是会出现并发问题。最后的结论是——不行!。
如果想要使用多线程,就需要每个线程中对应一个base,将线程里的事件注册到线程的base上。
下面是http多线程使用的使用方法
启动多线程http的服务
1 |
|
然后就是开启事件分发线程
1 | event_base_dispatch( w->base ); |
可以在看门狗中关闭事件分发循环,event_base_loopexit是可以设置延迟事件的,不设置是可以参数为空。
1 | struct timeval delay = { 0, 1 }; |
http服务器停止时,需要注意资源释放,以免内存泄漏
1 | event_free(w->watchdogEv); |
程序使用demo,只需要设置监听端口和要启动的线程数量即可,在程序停止的时候,调用stop会释放所有资源,避免内存泄漏。
1 | servers::HttpSrv s; |
程序源代码可以见公众号 xutopia77 文章 基于libevent的多线程http服务器
程序运行结果如下
1 | dispatch start |
postman请求测试
1 | GET http://192.168.31.106:8080/test |
本次在项目中用到了libevent库,目前程序运行基本稳定,没有出现异常情况, libevent是目前一个非常优秀的跨平台网络库,通过研究学习它,可以知道一个网络库的设计方法,虽然libevent库不是很胖发,但是他的设计思想还是很优秀的,但是短短的时间里想要彻底掌握所有的细节,还是有难度的,这里我只是简单的阐述了libevnet的基本运行机制和使用方法,没有做过多的深入研究,如果本章中有错误的地方,还希望读者朋友们能够指出来。
程序源代码可以见公众号 xutopia77 文章 基于libevent的多线程http服务器




