【问题标题】:Why the need for Async IO when reading sockets for non HTTP server为什么在读取非 HTTP 服务器的套接字时需要异步 IO
【发布时间】:2012-07-21 02:10:48
【问题描述】:

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

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

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

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

我看不出异步 io 将如何提高我的性能。

【问题讨论】:

    标签: c++ design-patterns boost-asio asyncsocket ace


    【解决方案1】:

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

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

    我希望这会有所帮助。

    【讨论】:

    • 我的应用程序确实是高频交易,是的,我确实需要持久化,但会有一个单独的进程来持久化数据,这些数据将使用某种共享内存或 IPC 共享。跨度>
    • 好的。如果您可以以非阻塞方式快速将持久性任务卸载到另一层,那么您可能会赢。 @lserni(下)的分析非常出色。
    • 仍在试图弄清楚如何“以非阻塞方式卸载持久性”.. 我不能从多个线程重新广播或多播到 localhost 吗? OS 不会通过 UDP 从并发发送中创建单个流,然后异步执行所有这些操作吗?我的操作系统现在是 windows,但操作系统应该无关紧要。 ty
    【解决方案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 减少到其值的一小部分(仅调度时间)。从某种意义上说,异步也是如此,但需要更多的时间,并为您处理更多的编程样板。

    【讨论】:

    • 试图跟随但不确定 N 的作用。在我的情况下,N 是 1 或 3,不完全确定套接字向量是什么。但我再次认为这是由于通信协议造成的误解。 http与其他。每个套接字都有不同的数据和它唯一的下游......我是客户端。消息具有一定的依赖性,但可以用作逻辑独立的。我认为我的设计是“水平扩展”,尽管我只了解您的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多