【问题标题】:Twisted - Pass Protocol (and socket handle) object to Twisted subprocessTwisted - 将协议(和套接字句柄)对象传递给 Twisted 子进程
【发布时间】:2014-11-13 22:45:35
【问题描述】:

使用下面的代码,我似乎可以很容易地使用 multiprocessing.reduction 在子进程中重建套接字..

import socket,os
import multiprocessing
from multiprocessing.reduction import reduce_handle, rebuild_handle

client = socket.socket()
client.connect(('google.com', 80))

rd = reduce_handle(client.fileno())

print "Parent: %s" % (os.getpid())

def test(x):
        print "Child: %s" % (os.getpid())

        build = rebuild_handle(x)
        rc = socket.fromfd(build, socket.AF_INET, socket.SOCK_STREAM)
        rc.send('GET / HTTP/1.1\n\n')
        print rc.recv(1024)

p = multiprocessing.Process(target=test, args=(rd,))
p.start()
p.join()

我有一个同时运行多场比赛的 Twisted 游戏服务器。这些比赛可能包含几个玩家,每个玩家都有一个协议实例。我想做的是将匹配拆分到 Twisted 子进程池中,并让池处理他们自己处理的匹配的客户端。似乎读取/写入客户端的数据并将该数据传入和传出子进程将是不必要的开销。

协议保证是 TCP 实例,所以我相信我可以(如上面的代码)像这样减少套接字:

rd = reduce_handle(myclient.transport.fileno())

通过查看 Twisted 源将数据传递给子进程后,我现在似乎可以像这样在子进程中重建它:

import socket
from twisted.internet import reactor, tcp
from multiprocessing.reduction import reduce_handle, rebuild_handle

handle = rebuild_handle(rd)
sock = socket.fromfd(handle, socket.AF_INET, socket.SOCK_STREAM)
protocol = MyProtocol(...)
transport = tcp.Connection(sock, protocol, reactor=reactor)
protocol.transport = transport

我只是想试试这个,但鉴于我对 Twisted 的内部结构并不十分熟悉,即使这可行,我也不知道这可能会产生什么影响。

谁能告诉我这看起来是否正确以及是否可行?出于某种原因,这是不可取的吗(我从未在 Twisted 文档或帖子中看到过它,尽管它看起来很相关)?如果这行得通,我应该注意什么?

提前致谢。

【问题讨论】:

    标签: python sockets multiprocessing twisted


    【解决方案1】:

    Twisted 和多处理模块彼此不兼容。如果代码看起来可以工作,那只是运气和意外,未来版本(很可能没有多处理的未来版本,但可能会有 Twisted 的未来版本)可能会将这种好运气变成坏运气。

    twisted.internet.tcp 也不是在您的应用程序中使用的好模块。它并不完全是私有的,但你也不能依赖它总是与你的应用程序使用的反应器一起工作。例如,iocp reactor 使用twisted.internet.iocpreactor.tcp,而与twisted.internet.tcp 完全不兼容(我不认为您很可能会在此代码中使用iocp reactor,而Twisted 附带的其余reactor 确实使用twisted.internet.tcp 但第三方反应器可能不会,未来版本的 Twisted 可能会改变反应器的实现方式)。

    您要解决的问题有两个部分。一部分是在两个进程之间传递文件描述符。另一部分是说服反应器开始监视文件描述符并调度其事件。

    multiprocessing.reduction 与 Twisted 一起使用的风险可能很小,因为该模块中的进程管理似乎没有任何关系。相反,它只是关于酸洗套接字。因此,您可能能够使用该方法继续传达您的文件描述符(如果您出于某种原因想避免在父进程中使用 Twisted,您可能希望这样做 - 我不确定,但听起来并不就像这样)。但是,另一种方法是使用twisted.python.sendmsg 通过 UNIX 套接字传递这些描述符 - 或者更好的是,使用更高级别的层为您处理繁琐的sendmsg 位:twisted.protocols.amp。 AMP 支持作为文件描述符的参数类型,让您可以在进程之间传递文件描述符(同样,只能通过 UNIX 套接字),就像传递任何其他 Python 对象一样。

    至于第二部分,你可以使用reactor.adoptStreamConnection添加一个已经建立的到reactor的TCP连接。这是一个您可以依赖的公共接口(只要反应器实际实现它 - 并非所有反应器都这样做:如果您想做某种优雅的降级或用户友好的错误,您可以使用 twisted.internet.interfaces.IReactorSocket.providedBy(reactor) 内省反应器报告)。

    【讨论】:

    • multiprocessing.reduction 似乎是跨平台的(Windows 和 unix),只要您能够访问 Twisted 中的原始套接字,而 sendmsg 似乎是特定于 unix 的。这是一个直接的缺点,但是,无论如何我都没有在 Windows 上工作。除此之外,这一切都说得通。谢谢!
    猜你喜欢
    • 2013-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多