为什么cpu在同一个套接字上的多进程epoll时不平衡?

时间:2016-10-22 03:45:52

标签: multithreading sockets linux-kernel epoll

我有一个接收传入连接的高性能服务器,主进程在tcp端口上侦听/绑定,并将自己分叉给一些工作者。 然后,工作人员使用epoll来监视传入的连接事件,如果事件发生,则尝试接受连接。

它运行良好,但是当我计算每个工作人员处理的连接数(或每个工人消耗的CPU工具数)时,我发现它根本不平衡。

例如:

一个忙碌的工人:处理10k连接,消费者20%CPU; 一个空闲工作者:处理300个conenctions,消费者4%CPU;

我的服务器在RHEL6.5操作系统(2.6.32内核)上运行。

有人可以帮我解决这个问题吗?

编辑:

为什么

在挖掘了一些内核代码(2.6.32.x)后,我发现了为什么会出现平衡。

1 * MasterProcess:创建并绑定Listen套接字;
n * WorkerPrecess:创建epfd并监视来自master的listen socket。

当WorkProcess epoll_ctl(...,listen_sock,...)时,内核将监视文件添加到epoll结构的rbtree(@see fs / eventpoll.c ep_insert)并将epoll结构添加到wait_queue listen_sock通过回调(ep_ptable_queue_proc)

static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
             poll_table *pt) {
    ...
    add_wait_queue(whead, &pwq->wait);
    ...    
}
//whead is the waitqueue of listen socket, 
//and the *pt is a container of epfd's releated resource.

当一个新连接进入(SYN_REC)时,监听套接字的事件已被更改,内核将迭代等待等级通过epoll给出的回调将该事件通知给套接字上的所有epoll监视器。回调是 ep_poll_callback (@see fs / eventpoll.c),回调将唤醒epoll_wait系统调用的进程(或线程)等待。

在通知过程之后,listen socket的waitqueue序列不会改变。并且将通过修复订单通知事件等待进程。提前唤醒的进程应该有更多的连接来处理与最后一个进程得到通知。这导致了失衡。

FIX

1 * MasterProcess为所有WorkerProcess创建一个epfd; 2 * WorkerProcess通过epoll_wait等待同一个epfd;

在这种情况下,我们在内核级别只有一个 epoll结构。当事件发生时,将仅调用一个 epoll结构的等待call_back。

epoll结构的唤醒回调是:

static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key)

现在,所有WorkerProcess的boss线程都在epoll_wait上等待,而ep_poll_callback只会 唤醒其中一个。

当一个WorkerProcess被epoll唤醒时,它将从wait_queue中删除自己,如果调用了epoll_wait,则将它们重新添加到wait_queue的尾部。所以,我们可以逐个唤醒WorkerProcess。

1 个答案:

答案 0 :(得分:0)

没有问题。

拥有多名工作人员的目的是至少有一名工作人员可以使用,即使其他工作人员很忙。

但是当多个工作人员在等待时,哪个人获得该事件并不重要。进程/线程不会因为它运行较长时间而耗尽。

没有平衡,因为内核不关心。你也不应该。