多线程服务器的常见编程模型

2020-09-21  本文已影响0人  CP3fans

多线程服务器的常见编程模型

IO Models

image

A ->[tcp send buffer] --->[tcp recv buffer]-> B

Blocking IO : A send data 发送缓冲区满或 B recv data接收缓冲区空 会阻塞当前线程

NonBlocking IO: 和Blocking IO不同的是,send或者recv直接返回错误(需要轮询调用)

IO Multiplexing:通过Select/Poll/Epoll等系统调用监控多个连接上的读写事件

Thread Models

Blocking IO + One Thread Per Connection

Blocking IO + Thread Pool (Tomcat BIO)

IO Multiplexing + Thread Pool (Tomcat NIO)

IO Multiplexing + One Thread One Loop *

One Thread One Loop思想

一个线程一个循环流程

Loop结构

void CReactor::Run()
{
    //线程退出标志
    m_bShouldRun = true;
    while(m_bShouldRun)
    {
        //处理其他的任务
        handle_other_task();
        //利用select/pool/epoll等I/O多路复用监听各个连接(fd)的读写事件
        select_or_epoll_function();
        //处理各个连接(fd)的读写事件
        handle_io_event();
        //处理定时器
                check_timer();
        //处理同步或者异步事件
        dispatch_event();
    }
}

线程分工(front)

front线程交互

AcceptReactor

1、监听是否有新的客户端连接(Listenfd上是否有读事件发生)。

2、有新连接则生成新连接的socket(clientfd),并将该socket传递给frontReactor。

Q:线程之间如何传递?

SendEvent Or PostEvent

Q:新连接分配策略?

Round Robin(轮询) 缺点:负载均衡有点问题

TresultReactor

1、订阅tserver发布的流水,接收到流水中的XTP报文,存到TradeResult(CachedFlow)中。

FrontReactor

1、通过Epoll或者Select系统调用监听该线程所负责Socket连接上的读写事件

2、收包(收网络数据,放缓冲区,解包并处理) 发包(....)

3、从TradeResult(cachedFlow)中读取从tserver发布的XTP报文,并处理。

Q:TresultReactor放到TradeResult流中数据,怎么及时让FrontReactor来处理呢?(效率问题)

    int nfds = epoll_wait(m_fdEpoll, events, EPOLL_MAX_EVENTS, timeout);

1、timeout设置为0

如果handleothertask没有事做,同时socket没有IO读写事情,线程空转,浪费CPU时间片。

2、timeout设置为10ms

如果没有网络IO时间发生,epoll_wait需要挂起timeout时间才能返回,这样当有其他任务发生,handle_other_task()就会延时处理,TradeResultFlow交易结果流中的数据,frontReactor不能及时处理。

解决方案:

创建eventfd(唤醒fd),并把eventfd绑定到epollfd中,当我们想唤醒直接去执行handle_other_task()时,往eventfd中写入一个字节,该eventfd就变成可读,epoll_wait就立马返回,接下来就可以处理handle_other_task()里面的任务了。

上一篇下一篇

猜你喜欢

热点阅读