使用多个进程共享连接和数据的最快方法?

时间:2009-09-30 16:16:03

标签: c++ sockets ipc shared-memory latency

我有多个应用程序进程,每个进程都连接到服务器并从中接收数据。通常连接到的服务器和正在检索的数据在进程之间重叠。因此,网络中存在大量不必要的数据重复,需要的连接数量超过了必要的数量(对服务器征税),数据最终会被冗余地存储在应用程序的内存中。

一种解决方案是将多个应用程序流程合并为一个 - 但在大多数情况下,它们在逻辑上是截然不同的,这可能是多年的工作。

不幸的是,延迟非常重要,而且数据量巨大(任何一个数据都不会太大,但是一旦客户端发出请求,服务器会随着数据的变化发送快速的更新流,这可以超过20MB / s,这些都需要以最短的延迟提供给请求的应用程序)。

我想到的解决方案是编写一个本地守护程序进程,应用程序进程将从中请求数据。守护程序将检查是否已存在与相应服务器的连接,如果没有,则进行连接。然后它会检索数据并使用共享内存(由于延迟问题,否则我会使用套接字)将数据提供给请求应用程序。

在短期内简单的想法,只解决了冗余连接是使用UNIX域套接字(这将在UNIX操作系统上运行,但我更愿意坚持到跨平台库的时候,我可以)共享一个socket描述符在所有进程之间,所以它们共享一个连接。这个问题就是消耗缓冲区 - 我希望所有进程看到套接字上的所有内容,如果我理解这种方法,那么套接字上的一个进程中的读取将阻止其他进程在其上看到相同的数据下一次读取(共享描述符中的偏移量将被碰撞)。

2 个答案:

答案 0 :(得分:3)

我建议你看看ZeroMQ。这可能有助于解决您的问题。我不认为20MB / s是非常高的......你应该能够通过在ZeroMQ中使用TCP传输来达到这种吞吐量水平。还支持其他传输机制,包括使用OpenPGM的可靠多播。有计划将UNIX管道添加为传输机制。

消息传递可能比共享内存更安全,更容易。值得注意的是,如果您使用消息传递而不是共享内存,那么您可以在一组服务器上拆分应用程序组件...这可能会比共享内存提供更好的性能,具体取决于您的瓶颈所在。

答案 1 :(得分:2)

我相信通过共享内存公开数据的专用服务是您最好的选择。其次是通过命名管道多播数据的服务,除了你的目标是Unix变体而不是Windows。

另一种选择是UDP多播,因此数据复制发生在硬件或驱动程序级别。唯一的问题是UDP数据传输不能保证有序,也不能保证完全传送。

我认为共享物理套接字是一个黑客,应该避免,你最好实现一个驱动程序,它做了你想让守护进程透明地做的事情(例如,进程看到套接字是一个普通的套接字,除了内部套接字是映射到单个套接字,其中存在逻辑以在虚拟套接字之间重新广播数据。)不幸的是,正确的努力水平将是重要的,如果时间完成是一个问题共享套接字不是真正的好的路由(无论是在驱动程序级别完成,还是通过其他一些hacky方式完成,例如共享套接字描述符交叉进程。)

共享套接字还假定它是一个只推送连接,例如在应用级别没有进行流量协商(例如,数据请求或数据接收确认。)

完成的快速路径可能是查看BNC等项目并转换代码或劫持一般想法,以满足您的需求。将流量复制到本地套接字不应该产生巨大的延迟,尽管您将为所有数据复制执行NIC(和相关缓冲区),并且如果您接近硬件限制(或者驱动程序和/或驱动程序不佳) TCP堆栈实现)然后你可能会结束死机。在我工作的地方,我们已经看到数据复制在驱动程序层面上是一个千兆以太网卡,所以这并不是闻所未闻。

共享内存是最好的选择,如果您希望保持平台独立性和高性能,同时不会引入任何因内核或硬件/驱动程序更改而在5年内可能无法支持的内容。