1

我正在设计一个 C++ 客户端应用程序,它侦听多个端口以获取短消息流。在阅读了 ACE、POCO、boost::asio 和所有类似 Proactor 的设计模式之后,我即将开始使用 boost::asio。

一件事我注意到它是使用异步套接字 IO 的不变主题,但还没有阅读 async io 解决的好的问题描述。所有这些设计模式都是基于 HTTP Web 服务器设计的假设吗?

由于 Web 服务器是复杂延迟敏感并发套接字编程的最常见应用程序,我开始怀疑这些模式/习语中的大多数是否适合这一应用程序。

我的应用程序将侦听一些套接字以获取简短而频繁的消息。一个单独的线程将需要组合所有消息进行处理。我正在研究设计模式的一件事是将连接管理与数据处理分开。我希望连接在断开连接后尝试重新连接,并让处理线程继续,就好像什么都没发生一样。这里推荐什么设计模式?

在我的情况下,我看不到 async io 将如何提高性能。

4

2 回答 2

3

你在正确的轨道上。问“为什么”很聪明,尤其是在围绕异步和事件驱动的所有炒作中。除了网络之外,还有其他应用程序。考虑消息队列和金融交易,如高频交易。基本上任何时候等待花费金钱或失去为客户服务的机会都是异步的候选者。网络就是一个很好的例子,因为网络比数据库快得多。与往常一样,对您的应用询问“这是否有意义”。如果您没有从中受益,异步会增加很多复杂性。

如果消息之间的平均时间与处理每条消息所需的时间相当,那么您的简短、快速的消息实际上可能会从异步中受益很多,特别是如果该处理包括持久性。但是你不必急于异步。检测你的阻塞代码,看看你是否真的有瓶颈。

我希望这有帮助。

于 2012-07-22T17:37:56.320 回答
2

使用阻塞调用模式需要:

1. Listening on a socket vector of size N
2. When a message arrives, you wake up with a start in time K, find and start processing the message, employing a time T (it does not matter if the processing is offloaded to another thread: in this case T becomes your offloading time)
3. You finish examining the vector and GOTO 1

所以你可能会说,如果有 M 条消息到达,而另一条消息在 K+M*T 调度时间内到达,那么第 M+1 条消息会发现自己在等待 K+M*T 时间。这对于您的 K(常数)、M(流量函数)和 T(资源和系统负载函数)的预期值是否可以接受?

异步处理,嗯,实际上并不存在。在某个地方总会有一个“同步”IO 循环,只有它会很好地集成到内核(甚至硬件)中,以至于它的运行速度比您自己的快 10-100 倍,因此可能会在较大的值下更好地扩展M 的延迟仍然是 K1+M*T1 的形式,但是这次 K1 和 T1 要低得多。或者 K1 稍微高一点,而 T1 明显更低:对于大的 M 值,架构“扩展得更好”。

如果您的 M 值通常较低,则异步的优势按比例较小。在应用程序生命周期中只有一条消息的荒谬情况下,同步或异步几乎没有区别。

考虑另一个因素:如果消息的数量真的很大,异步有它的优势;但是如果消息本身是独立的(由消息 A 引起的更改不影响消息 B 的处理),那么您可以保持同步并水平扩展,准备一个数量为 Z 的“消息集中器”,每个接收部分 M/Z总流量。

如果处理需要对其他服务执行其他调用(缓存、持久性、信息检索、身份验证......),增加 T 因子,那么最好转向多线程甚至异步。使用多线程,您可以将 T 减少到其值的一小部分(仅调度时间)。从某种意义上说,异步也是如此,但剃须更多,并为您处理更多的编程样板。

于 2012-07-22T20:07:23.357 回答