记录Libevent延迟读回调问题的发现和解决

在开发一个基于Libevent的及时通讯App时,遇到客户端Request包与Server响应的Response包之间出现30s至2min的延迟问题。通过接入层日志分析和Tcpdump抓包,定位到问题是由于Libevent的延迟读回调导致,进一步发现是包堆积在Epoll的LT模式下未被及时处理。解决方案是修改读回调逻辑,检查outbuffer是否有剩余数据并处理。这次经历加深了对Reactor工作模式的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景描述:       

       最近做一个Mini项目,实现包括语音的及时通讯App,我负责后台的开发。底层的网络收发框架采用的是Libevent的bufferevent,是一个基于事件驱动的高效异步I/O框架,接口简单易懂,采用linux内核的Epoll实现网络事件触发。经过封装用在项目中,在和终端测试时出现问题:终端发送的Request包,Server回应的Response包居然延迟30s---2min不等。简直不能忍!

问题定位:

       由于服务器架构分为介入层+逻辑层+存储层,每个来自终端的请求包,都要经过接入层的转发,在对应的逻辑层进行处理和响应。延迟的时间是在客户端?接入层?逻辑层?一个请求包从终端发出到接受到对应响应包为整个流程,可分为如下几个时间段:


libevent是一个轻量级的事件驱动网络库,它提供了一种高效的方式来处理各种类型的事件,包括网络连接、定器等。在libevent中,你可以创建一个事件结构体(如ev_io或ev_timer),然后将你的回调函数注册到这个结构体上。 以下是一个简单的步骤说明: 1. **初始化**:首先需要包含`<event2/event.h>`头文件,并调用`event_base_new()`创建一个事件基础基(Event Base)。 ```c struct event_base *base = event_base_new(); ``` 2. **创建事件句柄**:根据你需要监听的事件类型(例如事件、写事件或定器),使用相应的构造函数创建事件,如`ev_io_new()`。 ```c struct ev_io *watcher = ev_io_new(base, sockfd, EV_READ | EV_PERSIST); // sockfd是套接字描述符 ``` 3. **设置回调函数**:通过`ev_set()`函数,将你的回调函数关联到事件句柄上,通常这个函数会在事件发生被执行。回调函数一般接收一个指向事件的指针作为参数。 ```c void my_callback(struct ev_loop *loop, struct ev_io *w, int revents) { // 这里是你处理事件的代码 } event_set(watcher, -1, EV_WRITE | EV_READ, my_callback, watcher); ``` 4. **添加事件到循环**:将事件加入到事件循环中,通常是在一个事件循环开始前调用`event_add()`。 ```c event_add(watcher, NULL); ``` 5. **启动事件循环**:最后,使用`event_run()`开始事件循环,直到有事件触发回调或手动退出。 ```c if (event_base_dispatch(base) == -1) { perror("Error running event loop"); } ```
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值