Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于 定时器 和 消息队列 的 映射问题 #50

Closed
chenneal opened this issue Mar 29, 2017 · 4 comments
Closed

关于 定时器 和 消息队列 的 映射问题 #50

chenneal opened this issue Mar 29, 2017 · 4 comments

Comments

@chenneal
Copy link
Contributor

chenneal commented Mar 29, 2017

@lynncui00
最近阅读源码读到了 定时器 和 消息队列 两个结构。

其中定时器存在 Timer 实例的 m_vecTimerHeap 结构中,这是一个小顶堆的 vector 。
消息队列放在 IOLoop 实例的 m_oMessageQueue 结构中,是一个 string 的 Queue 。

每次 IOLoop() 的时候先处理已经超时的事件,这个我明白;但是在处理完超时时间后,每次 OneLoop() 都会弹出一个 m_vecTimerHeap 中最小的超时定时器,然而对应的 message 居然是 oMessageQueue 队首的那个消息节点,然而两者并不存在对应关系

假设一个场景,我设定一个恒定增长的物理时间轴,在物理时间 100s 的时候我做了动作 A 并设定 timeout 为 300s,在物理时间 200s 的时候我做了动作 B 并设定超时为 100s 。某个时候假设两者在都收到了 reply 消息加入了 oMessageQueue 队列, 只是 A 的 reply 先到,loop 的时候两者也都没有超时,我先拿出的是 B 动作的超时时间(因为 m_llAbsTime 更小),但是处理的却是 A 的消息。

详情见 IOLoop.cpp 的 void IOLoop :: OneLoop(const int iTimeoutMs) 函数。

我认为定时器向量 vecTimerHeap 和消息队列 m_oMessageQueue 应该维护一个映射关系。 否则 timeout 的大小会影响消息事件的处理。

@chenneal chenneal changed the title 关于 定时器 和 消息队列 的 映射问题。 关于 定时器 和 消息队列 的 映射问题 Mar 29, 2017
@buptmiao
Copy link

个人认为定时器和消息队列本来就没有一一对应关系,而是两类事件,一个是时间事件一个是消息事件。这个模式在redis中也有类似应用。关键代码在 Oneloop中的这一行:

bool bSucc = m_oMessageQueue.peek(psMessage, iTimeoutMs);

该timeout值是时间堆中的最小超时时间,这个时候程序阻塞timeout ms。如果来消息了,阻塞退出,执行消息。如果直到超时都没接到消息,那么同样阻塞退出,下一个loop执行该超时事件。这样设计的目的是使得两类事件都能够及时和准时执行。

@chenneal
Copy link
Contributor Author

chenneal commented Mar 30, 2017

@buptmiao 感谢你的回复,你说的那个函数我是看过的,iTimeoutMs 只是作为锁等待最大时间的依据而已。你说的确实在理,这样的处理应该算是一种优化处理。但是这样 A 虽然是按照消息的顺序处理完毕,但是事实 B 我们是变向的增加了它的超时时间的(将 A 多余的时间过渡给了 B),某些情况会导致发现 B 的超时事件处理动作是往后延迟的,不过这对程序的正确性肯定是没有影响的。

你说的 A 和 B 都能够去处理,但是其实按照原本的超时设定 B 应该是直接去处理超时事件了才对。

@buptmiao
Copy link

时间堆里面的时间都是绝对时间,导致事件处理滞后的原因可能来自前一个事件的处理函数执行时间过长。

@chenneal
Copy link
Contributor Author

chenneal commented Apr 1, 2017

这几天又看了一下,开始的理解确实有误。phxpaxos 每次会再发送 message 到其它节点之前会设定一个定时器,待接收到其它节点发来的 message 时会扔到 消息队列 之中,之所以先取出最小的 timer 作为阻塞依据是为了不妨碍下一个超时事件的处理。

@chenneal chenneal closed this as completed Apr 1, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants