-
Notifications
You must be signed in to change notification settings - Fork 861
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
Comments
个人认为定时器和消息队列本来就没有一一对应关系,而是两类事件,一个是时间事件一个是消息事件。这个模式在redis中也有类似应用。关键代码在 Oneloop中的这一行:
该timeout值是时间堆中的最小超时时间,这个时候程序阻塞timeout ms。如果来消息了,阻塞退出,执行消息。如果直到超时都没接到消息,那么同样阻塞退出,下一个loop执行该超时事件。这样设计的目的是使得两类事件都能够及时和准时执行。 |
@buptmiao 感谢你的回复,你说的那个函数我是看过的,iTimeoutMs 只是作为锁等待最大时间的依据而已。你说的确实在理,这样的处理应该算是一种优化处理。但是这样 A 虽然是按照消息的顺序处理完毕,但是事实 B 我们是变向的增加了它的超时时间的(将 A 多余的时间过渡给了 B),某些情况会导致发现 B 的超时事件处理动作是往后延迟的,不过这对程序的正确性肯定是没有影响的。 你说的 A 和 B 都能够去处理,但是其实按照原本的超时设定 B 应该是直接去处理超时事件了才对。 |
时间堆里面的时间都是绝对时间,导致事件处理滞后的原因可能来自前一个事件的处理函数执行时间过长。 |
这几天又看了一下,开始的理解确实有误。phxpaxos 每次会再发送 message 到其它节点之前会设定一个定时器,待接收到其它节点发来的 message 时会扔到 消息队列 之中,之所以先取出最小的 timer 作为阻塞依据是为了不妨碍下一个超时事件的处理。 |
@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 的大小会影响消息事件的处理。
The text was updated successfully, but these errors were encountered: