rpc-server端IO服务模型实现:epoll线程池

本文介绍了一种基于epoll和共享内存的RPC服务设计方案。该方案利用epoll的高效I/O复用特性来处理大量并发连接,同时采用生产者-消费者模式管理连接池中的请求任务。此外,还讨论了epoll_wait超时时间设置及处理可读连接时移除epoll监听的原因。

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

(一)功能

        rpc(远程函数调用)提供client端通过网络调用远程server端的函数的服务。

        rpc-server端需要提供较高的吞吐能力,支持较大的并发连接。

(二)设计思路

  • epoll监听多个连接fd,实现IO复用

        1)epoll没有最大并发连接的限制,上限是最大可以打开文件的数目,一般远大于2048

        2)epoll效率高,只管活跃的连接,而跟连接总数无关

        3)使用共享内存,省去了内存拷贝

  • 生产者&消费者模式对请求任务进行管理

        一个IO-thread线程维护连接池中的连接,连接有3种状态:NO_USED、READY、BUSY。

        1)NO_USED状态,fd位置空闲,连接位尚未使用

        2)READY状态,已经与client端连接连接的fd,等待请求事件

        3)BUSY状态,已经收到请求事件,将fd放入任务队列,等待work-thread处理

  • 以单个请求事件为任务单位放入队列

        将连接放入任务队列,work-thread处理完这个请求后,该fd继续变为READY放入连接池,等待新的请求到来。因此,一个连接上的请求可能被多个work-thread线程处理。

  • 管理连接池中连接,设置超时时间

        某个连接超过一个时间没有事件到来时,服务端主动断开连接;每个连接的nLastActive字段记录上次事件到来orBUSY状态的时刻。

(三)流程

 

 

(四)数据结构

  • PendingPool连接池
序号字段类型含义
1m_listen_fdint监听客户端请求的fd
2m_aySocketSItem*存放已与client建立的连接对象集合
3m_socketNumint连接池size
4m_ayEventepoll_event*记录epoll监听到的活跃事件
5m_eventNumintepoll监听的活跃事件size
6m_ayReadyint*任务队列,有可读事件的fd
7m_queueLenint队列长度
8m_mutexpthread_mutex_t互斥锁,控制出队
9m_conditionpthread_cond_t条件锁,控制入队、出队
  • SItem连接对象
序号字段类型含义
1nLastActiveint该连接最后一次活跃时间记录秒数
2statusint连接状态0:未使用;1:已建立连接;2:可读
3epoll_statusint是否加入epoll监听0:未监听;1:已监听
4processorshared_ptr<TProtocol>*thrift协议对象 

 

(五)实现

  • mask

=> 将连接池中的READY连接加入epoll监听

  • pool_epoll_wait

=> 等待epoll监听的fd有事件发生

  • deal_work

=> 依次处理所有有事件的fd

1)listen_fd=>有新的连接请求,accept建立新的socket,并放入连接池

2)其他socket=>有可读请求,从epoll中取消监听&将socket放入任务队列;其他事件,关闭连接

  • fetch_item

=> 从任务队列取出fd

 

(六)使用

  • IO-thread线程

        即处理接收请求的线程。其使用epoll监听listen_fd和多个client端fd,并处理epoll监听到的所有事件。

 

  • work-thread线程

不断从任务队列取出可读的fd任务,调用对应的函数处理请求,然后将fd继续放入连接池给epoll监听。

 

(七)问题

  • epoll_wait的超时时间设置

        IO-thread线程经历mask->wait->deal->checktimeout的循环,在deal时会将有请求的连接fd从epoll监听中移除

        如果mask时该请求未执行完成,则mask时该fd不加入监听

        如果此时1)没有新连接2)其他连接没有新请求,则该IO-thread线程要等待epoll超时时间才能重新监听该fd

        而如果该fd的此次执行消耗1ms&下次请求在第2ms,而epoll超时设置为1000ms,则该fd的下次请求要等待999ms才能被epoll监听到

        因此,当连接数or请求较少时,client的耗时近似于max(执行耗时,epoll_wait时间),进而,epoll_wait设置为server端请求平均处理时间较为合理

  • deal中处理可读的连接(有请求)为什么要将fd从epoll监听中移除

        如果epoll继续监听该fd,且该fd上又有新的请求,则该fd再次被放入任务队列 => 任务队列中两个fd

        可能出现多个线程处理这个连接fd的情况,无法保证顺序性

 

转载于:https://www.cnblogs.com/taoxinrui/p/6408090.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值