zoukankan      html  css  js  c++  java
  • rpc-server端IO服务模型实现:epoll线程池

    (一)功能

            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连接池
    序号 字段 类型 含义
    1 m_listen_fd int 监听客户端请求的fd
    2 m_aySocket SItem* 存放已与client建立的连接对象集合
    3 m_socketNum int 连接池size
    4 m_ayEvent epoll_event* 记录epoll监听到的活跃事件
    5 m_eventNum int epoll监听的活跃事件size
    6 m_ayReady int* 任务队列,有可读事件的fd
    7 m_queueLen int 队列长度
    8 m_mutex pthread_mutex_t 互斥锁,控制出队
    9 m_condition pthread_cond_t 条件锁,控制入队、出队
    • SItem连接对象
    序号 字段 类型 含义
    1 nLastActive int 该连接最后一次活跃时间 记录秒数
    2 status int 连接状态 0:未使用;1:已建立连接;2:可读
    3 epoll_status int 是否加入epoll监听 0:未监听;1:已监听
    4 processor shared_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的情况,无法保证顺序性

  • 相关阅读:
    ubuntu下文件安装与卸载
    webkit中的JavaScriptCore部分
    ubuntu 显示文件夹中的隐藏文件
    C语言中的fscanf函数
    test
    Use SandCastle to generate help document automatically.
    XElement Getting OuterXML and InnerXML
    XUACompatible meta 用法
    Adobe Dreamweaver CS5.5 中文版 下载 注册码
    The Difference Between jQuery’s .bind(), .live(), and .delegate()
  • 原文地址:https://www.cnblogs.com/taoxinrui/p/6408090.html
Copyright © 2011-2022 走看看