Python 关闭twisted服务器
我有一个怪癖,我用它把工作推给客户。该协议包含一个包含所有作业的队列。如果客户机请求新作业,则此队列耗尽后,服务器将断开客户机的连接。最终,这将使客户端无法连接,服务器将准备关闭 我的问题是: 一旦ServerFactory完成工作,是否有一个公认的最佳做法来关闭它? 我知道,对于客户端来说,最佳做法是使用连接和处理连接丢失,从而关闭父进程。但我不确定服务器是否也是如此 目前,我是这样处理关闭的:Python 关闭twisted服务器,python,tcp,server,twisted,Python,Tcp,Server,Twisted,我有一个怪癖,我用它把工作推给客户。该协议包含一个包含所有作业的队列。如果客户机请求新作业,则此队列耗尽后,服务器将断开客户机的连接。最终,这将使客户端无法连接,服务器将准备关闭 我的问题是: 一旦ServerFactory完成工作,是否有一个公认的最佳做法来关闭它? 我知道,对于客户端来说,最佳做法是使用连接和处理连接丢失,从而关闭父进程。但我不确定服务器是否也是如此 目前,我是这样处理关闭的: from twisted.application import internet, service
from twisted.application import internet, service
from twisted.internet import reactor
from twisted.internet.protocol import ServerFactory
from twisted.protocols.basic import LineReceiver
class ServerProtocol(LineReceiver):
"""Twisted Protocol for sending and receiving lines of bytes."""
clients = []
logger = logging.getLogger('launcher.Launcher.RunServer')
def connectionMade(self) -> None:
"""When a connection is made add the client to the clients list."""
self.clients.append(self)
def lineReceived(self, line: bytes) -> None:
"""Whenver a line is received send work to the sending client.
Parameters
----------
line
The message received from a client.
"""
msg = 'Received: ' + line.decode('utf-8') + ' from ' +\
self.transport.hostname
self.logger.info(msg)
if not self.queue.empty():
run = self.queue.get()
run_bytes = bytes(run, 'utf-8')
self.logger.info('Sending run bytes to %s',
self.transport.hostname)
self.sendLine(run_bytes)
else:
self.clients.remove(self)
self.transport.loseConnection()
if not self.clients:
self.logger.info('Shutting down RunServer')
self.reactor.stop()
class RunServer(object):
"""Class for containing twisted server components.
Parameters
----------
workers
List of workers that will serve as clients.
queue
Queue of runs to execute.
Attributes
----------
factory
Twisted ServerFactory for producing protocols.
"""
def __init__(self, queue: Queue) -> None:
self.factory = ServerFactory()
self.factory.protocol = ServerProtocol
self.factory.protocol.queue = queue
self.factory.protocol.reactor = reactor
def start(self) -> None:
"""Start the server and thereby the execution of runs."""
self.factory.protocol.reactor.listenTCP(80, self.factory)
self.factory.protocol.reactor.run()
如您所见,我正在将反应器存储在self.factory.protocol.reactor
中,并在所有作业用完且客户端断开连接后使用reactor.stop
我很确定我以前读过,这不是运行客户机的公认模式,我假设服务器也是如此,但我还没有看到一个好的例子。我必须相信我熟悉这个例子 绝对不需要RunServer类。子类化
ServerFactory
并将逻辑从RunServer.\uuuu init\uuu
放入子类\uuuuu init\uuuu
将允许相同的行为,并具有更好的控制。然后您可以定义一个main
方法,并使用react
,如文档中所述()
以下是更新的代码:
from twisted.internet.defer import Deferred
from twisted.internet import reactor
from twisted.internet.protocol import ServerFactory
from twisted.protocols.basic import LineReceiver
class QueueingProtocol(LineReceiver):
def connectionMade(self) -> None:
self.factory.connectionMade()
def connectionLost(self, reason) -> None:
self.factory.connectionLost(reason)
def lineReceived(self, line: bytes) -> None:
msg = 'Received: ' + line.decode('utf-8') + ' from ' +\
self.transport.hostname
self.logger.info(msg)
if self.factory.empty():
self.transport.lostConnection()
else:
run = self.factory.get()
run_bytes = bytes(run, 'utf-8')
self.logger.info('Sending run bytes to %s',
self.transport.hostname)
self.sendLine(run_bytes)
class QueueingFactory(ServerFactory):
protocol = QueueingProtocol
def __init__(self, queue) -> None:
self.queue = queue
self.connections = 0
self.queueHandled = Deferred()
def connectionMade(self) -> None:
self.connections += 1
def empty(self):
return self.queue.empty()
def get(self):
return self.queue.get()
def connectionLost(self, reason) -> None:
self.connections -= 1
if self.connections == 0 and self.empty():
self.queueHandled.callback("done")
def main(reactor, queue):
factory = QueueingFactory(queue)
reactor.listenTCP(80, factory)
return factory.queueHandled
然后您可以在需要的地方导入
main
,并调用react(main,[some_queue])
这没有什么明显的“错误”design@notorious.no我同意,但根据文档react
“是一种使用定义良好的完成条件启动应用程序的方法。”在这个AWS和Docker服务器的新时代,停止将更为常见。大多数当前的twisted服务器持续运行。我想向你重申你的剧本是有效的。很好的回答顺便说一句