0

我正在写类似下面的东西(直径协议),我需要实现一个计时器来监视会话挂起状态并在它们超过某个阈值时终止它们,最好的方法是什么?

请注意,我正在寻找算法。

Credit-Control Application Related Parameters
Tx timer

When real-time credit-control is required, the credit-control
client contacts the credit-control server before and while the
service is provided to an end user.  Due to the real-time nature
of the application, the communication delays SHOULD be minimized;
e.g., to avoid an overly long service setup time experienced by
the end user.  The Tx timer is introduced to control the waiting
time in the client in the Pending state.  When the Tx timer
elapses, the credit-control client takes an action to the end user
according to the value of the Credit-Control-Failure-Handling AVP
or Direct-Debiting-Failure-Handling AVP.  The recommended value is
10 seconds.
4

1 回答 1

0

您根本不需要计时器。

当您的应用程序使用 eg 接受新连接时accept(),您可以使用 eg 记录当前时间clock_gettime()(特别是使用CLOCK_BOOTTIME时钟,它需要 2.6.39 或更高版本的内核)。

在处理期间,尤其是在发送任何响应之前,您的代码必须检查连接(时间戳)是否还不太旧。

虽然实现起来非常简单,而且非常精确,但clock_gettime()调用并不是特别快。也就是说,它本身并不是一个缓慢的调用——没有更快的方法来获取当前时间——只是根据当前时间检查时间戳确实需要clock_gettime()每次调用一次,这可能会导致很多这样的调用来生成。

如果性能比准确性更重要,可以使用定时器中断。定时器中断在指定间隔后发生;他们可能会延迟。换句话说,虽然定时器中断在间隔过去之前绝不应该触发,但它们可以在之后的任何时间触发。因此,超时并不像上面那样严格。

当计时器结束时,信号处理程序设置一个连接/超时特定标志。您的函数不是检查时间戳,而是验证标志是否尚未设置。

由于 Linux 中的计时器是一种有限的资源(不是稀缺的,只是可能限制为少于可能的同时客户端连接的数量)——限制大约是getrlimit(RLIMIT_SIGPENDING),在我的机器上大约是四万——我建议不要创建一个单独的计时器对于每个连接使用timer_create()or timerfd_create()

相反,我会使用一个实时信号(SIGRTMIN+1例如)和一个(高优先级)线程循环sigwaitinfo(),在所有其他线程中阻塞信号,维护下一个超时事件。当sigwaitinfo()调用返回时,它还会注册新的超时事件;这样,任何线程都可以通过创建合适的结构来添加新的超时事件,将其添加到链或数组中,然后引发实时信号。该siginfo_t结构(请参阅sigaction()定义)说明信号是由计时器生成还是通过 eg 引发的sigqueue()

一般来说,使用定时器中断通常是首选,因为它的开销比重复比较时间戳和当前时间的开销要小,而且大多数应用程序并不关心超时是否有点晚(只要它永远不会太早) . 特别地,十秒超时对于一个客户端可能是 10.0s,对于另一个客户端可能是 10.1s。

很难说超时是否应该在您的情况下准确。您引用的规范似乎强调最小延迟,而具有确切的超时(甚至所有客户端的超时)似乎并不那么重要。我个人的观点倾向于使用定时器中断。

无论您为超时处理选择哪种方法,我都建议您从一开始就将超时处理设计到逻辑中。在这两种情况下,您的代码都需要定期检查连接是否超时;一种方法只是将当前时间与原始时间戳进行比较,另一种方法是标志。只要您设计了超时签入,您就不太可能错过任何需要检查超时条件以实现稳健可靠运行的地方。

希望这可以帮助。

于 2013-09-17T19:59:32.943 回答