0

我想创建一个小型 p2p 应用程序,它同时处理来自其他已知/受信任节点的传入数据(它主要将其存储在 SQLite 数据库中)。为了识别这些节点,在连接时,每个节点都会自我介绍,然后我的应用程序需要检查它是直接知道这个节点还是通过另一个节点间接知道这个节点。因此,我需要进行图形搜索,这显然需要处理时间,并且我想将其外包给一个单独的进程(甚至是多个工作进程?请参阅下面的第二个问题)。此外,在某些情况下,需要调整图形,添加新边或顶点。

假设我有4 个工作进程通过异步 I/O 接受和处理传入连接。他们访问(读取/修改)图表的最佳方式是什么?单个队列显然无法实现读取访问,因为我需要以某种方式将搜索结果传回。

因此,执行此操作的一种方法是另一个队列,该队列将由图形搜索过程填充,并且我可以将其添加到事件循环中。然后事件循环可以将结果传递给处理程序。然而,这种基于事件/回调的方法将使得必须始终将相应的套接字传递给回调,从而传递给队列——这很讨厌,因为套接字是不可挑选的。(更不用说回调导致意大利面条代码的事实了。)

我刚刚想到的另一个想法可能是为每个传入连接创建一个到图形进程的管道,然后在图形方面也执行异步 I/O。但是,为了避免回调,如果我理解正确,我需要一个使用yield from(即tulip / PEP 3156)的异步 I/O 库。还有其他选择吗?

关于图形方面的异步 I/O :这当然是一次处理许多传入请求的最佳方式,但进行图形查找是一项 CPU 密集型任务,因此可以从使用多个工作线程或进程中获益问题是:多线程允许共享数据,但 Python 的 GIL 在某种程度上否定了性能优势。另一方面,多个进程没有这个问题,但我如何在它们之间共享和同步数据?(对我来说,拆分图表似乎是不可能的。)有什么办法可以很好地解决这个问题吗?此外,将异步 I/O 与多线程/多处理混合在性能方面是否有意义?

4

1 回答 1

1

回答你的最后一个问题:确实如此!但是,恕我直言,问题是:混合事件和线程有意义吗?你可以查看这篇关于混合并发模型的文章:http ://bibliotecadigital.sbc.org.br/download.php?paper=3027

我的提示:从一个流程和一个事件循环开始,就像在郁金香模型中一样。我将尝试解释如何使用 tulip 让事件+异步 I/O(以及线程或其他进程)完全没有回调。

你可以有类似的东西accept = yield from check_incoming(),它应该是一个郁金香协程(check_incoming),并且在这个函数中你可以loop.run_in_executor()在线程/进程池中运行你的图形搜索(我稍后会解释更多)。此函数run_in_executor()返回一个 Future,您也可以在其中yield from tasks.wait([future_returned_by_run_in_executor], loop=self). 下一步将是result = future_returned_by_run_in_executor.result()最后返回Trueor False

进程池要求只能执行和返回可选择的对象。这个要求不是问题,但隐含的是图形操作必须自包含在函数中,并且必须以某种方式获取图形实例。线程池存在 GIL 问题,因为您提到了可能导致“获取-gil-冲突”的 CPU 绑定任务,但这在新的 Python 3.x GIL 中得到了改进。两种解决方案都有局限性..

所以..而不是池,您可以拥有另一个具有自己的事件循环的单个进程,只是为了管理所有图形工作并将两个进程连接到一个 unix 域套接字。

第二个进程,就像第一个进程一样,也必须接受传入的连接(但现在它们来自已知来源)并且可以像我之前所说的那样使用线程池,但它不会与第一个事件循环进程“冲突” (处理外部客户端的那个),只有第二个事件循环。共享相同图形实例的线程需要一些锁定/解锁。

希望它有所帮助!

于 2013-09-28T03:40:12.603 回答