可以在ForkingMixIn中重用一个进程,比如ThreadingMixIn重用一个线程吗?

时间:2014-09-10 08:50:35

标签: python multithreading multiprocessing xml-rpc

编辑:可能这个问题是错误的。我正在使用threading.current_thread()。ident获取线程ID,并且我为后续调用获得了相同的值,这使我认为线程被重用,但这似乎不是真正的线程ID。使用threading.current_thread()。name我为每个请求获得不同的名称,因此可能没有重用线程。除了我在问题中附加的文档是指xmlrpc-c库,而不是python' s。问题是我需要与另一个xmlrpc-python服务器的xmlrpc-c服务器通信。我的测试表明,当请求来自同一个连接时,xmlrpc-c会重用线程(因为我可以利用线程缓存),但我并不完全确定。


对不起,如果标题有点奇怪,但我不知道如何让它更清晰。

问题是,当使用带有ThreadingMixIn的XMLRPC服务器时,它会生成一个新线程来为每个请求提供服务,但它会使该连接保持打开状态一段时间,因此它始终是服务于使用该连接的所有请求的相同线程。这有一个限制,默认是使用相同连接的30个请求。这可以在"参数" ServerAbyss文档的一部分:

http://xmlrpc-c.sourceforge.net/doc/libxmlrpc_server_abyss.html#server_abyss_run_server

重用连接的方法是使用相同的ServerProxy对象将请求发送到XMLRPC服务器,而不是在调用之前立即创建新请求,我认为这是进行RPC调用的常用方法。 / p>

嗯,这种行为对我来说非常有用,因为它允许我利用一些线程缓存。但真正的改进是使用ForkingMixIn而不是ThreadingMixIn来实现这种行为。问题是,似乎ForkingMixIn总是生成一个新进程来处理请求,而不考虑请求是否来自已经打开的连接。

那么,有没有一种方法可以让ForkingMixIn重新使用"一个进程与ThreadingMixIn重用一个线程来处理从已打开的连接到达的请求的方式相同?

2 个答案:

答案 0 :(得分:2)

socketserver.ForkingMixIn不能这样做。

但是socketserver.ThreadingMixIn也没有,所以你的前提是错的。所以第一个问题是......你认为你在线程上有连接池,你没有它,你没有注意到问题,所以你确定你确实需要它吗?


如果你这样做,你将不得不自己编写mixin。幸运的是,您可以将ForkingMixIn子类化为启动和管理流程的繁重工作,并且只需在其上添加您自己的代码,它应该能够舒适地放在唯一有用的文档化方法中,{{3 }}

另外,与stdlib中的许多库一样,socketserver意味着可读且有用的示例代码以及有用的库,这就是文档链接到process_request的权利在顶部,这使事情变得更容易。


不幸的是,虽然将代码插入ForkingMixIn很容易,但设计和编写代码却不容易。

基本概念很简单:你有一个子进程缓存,键入连接。对于每个请求,您在缓存中查找连接,根据需要创建一个新子项,然后将请求传递给适当的子项。

不幸的是,这些步骤中的每一步都说起来容易做起来难。

嗯,不是第一个。那只是the source。但除此之外:

  • 什么是“连接”? XMLRPC是一种纯无状态请求 - 响应协议。如果假设每个地址都是连接,则会出现误报(一次运行两个客户端,或者同一个NAT内只有两个用户);如果你假设每个套接字都是一个连接,你会得到漏报(客户端可以,并且将会关闭套接字并根据他们想要的任何原因打开一个新套接字)。通常的答案是使用存储在HTTP cookie(或HTTP标头或XML元素)中的应用程序级会话,因此现在您必须编写或使用HTTP会话管理器(包括处理reap-on-timeout)。 / LI>
  • 你如何“将请求”传递给孩子? ForkingMixIn依赖于以下事实:请求是fork之前的局部变量,因此仍可作为本地变量发布 - fork。对于从缓存中提取的某个对象,情况并非如此。因此,您需要使用multiprocessing.QueuePipe或其他一些IPC机制。并且,虽然Queue使得任何可以腌制的东西变得微不足道,但是几乎可以肯定的是,请求对象不能被腌制,因为它包含诸如套接字文件之类的东西。因此,您需要编写将所有内容捆绑到可以传递的内容的代码 - 其中包括执行fd迁移(Python无法为您处理)或读取所有请求数据以传递该内容相反(所以另一方可以将其包裹起来,例如BytesIO以坚持self.rfile)。
  • 孩子如何回应?同样,ForkingMixIn依赖于它从其父级继承了wfile文件的事实,但同样,这显然不会在这里起作用。如果您还没有完成fd迁移,那么您需要通过IPC传回响应(例如,另一个Queue)。在这种情况下,您的父母必须阻止该IPC。因此,您需要使用ThreadingMixIn为每个请求创建一个线程,这样他们就可以等待您的子进程(或者一些替代机制,比如循环遍历所有IPC的子服务线程)可组合的期货或select - 管道或其他任何东西。

这一点在概念上都不是特别困难(会话超时问题除外),但这些都是很多代码。

答案 1 :(得分:1)

我认为这里的问题是将数据传递给流程。您可以为进程提供连接(因此它可以自行处理所有内容)但是您将永远不知道何时关闭连接或不再需要连接。此外,子进程在N次请求后无法轻松创建新连接。

或者您可以在父进程中保持连接,只需将数据传递给子进程(例如,通过stdout - > stdin管道)。但这意味着你必须多次复制每个字节(将它从父进程的接收缓冲区中取出,但它进入父进程的发送缓冲区,可能会在管道执行时复制它几次它的魔力,将其复制到孩子的输入缓冲区,...)然后再为结果的每个字节再做一遍。对于需要花费一些时间来处理的小型请求而言,这不是一个问题,但可能是我一直关注的问题。

相关问题