3

我有多个应用程序进程,每个进程都连接到服务器并从它们接收数据。通常,连接到的服务器和正在检索的数据在进程之间重叠。因此,整个网络中存在大量不必要的数据重复,超出应有的连接数量(这会对服务器造成负担),并且数据最终会冗余地存储在应用程序的内存中。

一种解决方案是将多个应用程序进程组合成一个进程——但在大多数情况下,它们在逻辑上确实是不同的,这可能需要多年的工作。

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

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

短期内只解决冗余连接的一个更简单的想法是使用 unix 域套接字(这将在 unix 操作系统上运行,尽管我更喜欢在可能的情况下坚持使用跨平台库)在所有进程,因此它们共享一个连接。这样做的问题是消耗缓冲区——我希望所有进程都能看到来自套接字的所有内容,如果我对这种方法的理解正确,则在套接字上的一个进程中读取将阻止其他进程在其上看到相同的数据下一次读取(共享描述符中的偏移量将被碰撞)。

4

2 回答 2

3

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

消息传递可能比共享内存更安全、更容易。值得注意的是,如果您使用消息传递而不是共享内存,那么您可以将应用程序组件拆分到一个服务器集群中……这可能会给您带来比共享内存更好的性能,具体取决于您的瓶颈所在。

于 2009-09-30T22:58:35.600 回答
2

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

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

我认为共享物理套接字是一种黑客行为,应该避免,最好实现一个驱动程序,该驱动程序可以透明地执行您希望守护程序执行的操作(例如,进程将套接字视为普通套接字,但在内部套接字映射到单个套接字,其中存在逻辑以在虚拟套接字之间重新广播数据。)不幸的是,要做到这一点的努力程度将是巨大的,如果完成时间是一个问题,那么共享套接字并不是一个真正的好途径采取(无论是在驱动程序级别完成,还是通过其他一些黑客手段,例如共享套接字描述符跨进程。)

共享套接字还假定它是仅推送连接,例如,在应用程序级别没有发生流量协商(例如,数据请求或数据接收确认。)

一个快速完成的路径可能是查看 BNC 等项目并转换代码,或者劫持总体思路,来做你需要的事情。将流量复制到本地套接字不应导致巨大的延迟,尽管您将为所有数据复制使用 NIC(和相关的缓冲区),并且如果您接近硬件的限制(或驱动程序较差和/或TCP 堆栈实现),那么您可能会遇到一个死机。在我工作的地方,我们已经看到数据复制在驱动程序级别存储了千兆以太网卡,因此并非闻所未闻。

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

于 2009-09-30T16:29:30.750 回答