使用 Twisted 应用程序框架¶
简介¶
受众¶
本文档的目标受众是希望以可重用、标准且易于配置的方式部署大量 Twisted 代码的 Twisted 用户。希望使用应用程序框架的 Twisted 用户需要熟悉开发 Twisted 服务器 和/或 客户端.
目标¶
介绍 Twisted 应用程序基础设施。
解释如何使用
.tac
文件和twistd
部署 Twisted 应用程序。概述现有的 Twisted 服务。
概述¶
Twisted 应用程序基础设施负责运行和停止您的应用程序。使用此基础设施可以免去编写大量样板代码,方法是将您的应用程序挂钩到现有的工具,这些工具管理守护进程、日志记录、选择 Reactor 等等。
管理 Twisted 应用程序的主要工具是一个名为 twistd
的命令行实用程序。 twistd
是跨平台的,是运行 Twisted 应用程序的推荐工具。
Twisted 应用程序基础设施的核心组件是 twisted.application.service.Application()
对象 - 代表您的应用程序的对象。但是,Application 不会提供任何您想直接操作的内容。相反,Application 充当应用程序提供的任何“服务”(实现 IService
的对象)的容器。您与 Application 基础设施的大部分交互将通过服务完成。
“服务”是指应用程序中可以启动和停止的任何内容。典型的服务包括 Web 服务器、FTP 服务器和 SSH 客户端。您的 Application 对象可以包含许多服务,甚至可以使用 MultiService
或您自己的自定义 IServiceCollection
实现来包含服务的结构化层次结构。您很可能希望使用它们来管理依赖于其他服务的服务。例如,代理 Twisted 应用程序可能希望其服务器服务仅在关联的客户端服务启动后才启动。
一个 IService
具有两个基本方法,startService()
用于启动服务,stopService()
用于停止服务。后者可以返回一个 Deferred
,表示服务关闭尚未完成,直到结果触发。例如
from twisted.internet import reactor
from twisted.application import service
from somemodule import EchoFactory
class EchoService(service.Service):
def __init__(self, portNum):
self.portNum = portNum
def startService(self):
self._port = reactor.listenTCP(self.portNum, EchoFactory())
def stopService(self):
return self._port.stopListening()
有关 EchoFactory
和 listenTCP
的解释,请参见 编写服务器。
使用服务和应用程序¶
twistd 和 tac¶
为了处理 Twisted 应用程序的启动和配置,Twisted 应用程序基础设施使用 .tac
文件。 .tac
是 Python 文件,用于配置一个 Application
对象并将此对象分配给顶层变量“application
”。
以下是一个简单的 .tac
文件示例
# You can run this .tac file directly with:
# twistd -ny service.tac
"""
This is an example .tac file which starts a webserver on port 8080 and
serves files from the current working directory.
The important part of this, the part that makes it a .tac file, is
the final root-level section, which sets up the object called 'application'
which twistd will look for
"""
import os
from twisted.application import internet, service
from twisted.web import server, static
def getWebService():
"""
Return a service suitable for creating an application object.
This service is a simple web server that serves files on port 8080 from
underneath the current working directory.
"""
# create a resource to serve static files
fileServer = server.Site(static.File(os.getcwd()))
return internet.TCPServer(8080, fileServer)
# this is the core part of any tac file, the creation of the root-level
# application object
application = service.Application("Demo application")
# attach the service to its parent application
service = getWebService()
service.setServiceParent(application)
twistd
是一个程序,它使用 .tac
文件运行 Twisted 应用程序。在最简单的形式中,它接受一个参数 -y
和一个 tac 文件名。例如,您可以使用命令 twistd -y service.tac
运行上述服务器。
默认情况下,twistd
会守护进程并记录到名为 twistd.log
的文件中。更常见的是,在调试时,您希望应用程序在前景运行并将日志记录到命令行。要像这样运行上述文件,请使用命令 twistd -noy service.tac
。
有关更多信息,请参见 twistd
手册页。
自定义 twistd
日志记录¶
twistd
的日志记录可以通过命令行进行自定义。这需要一个可导入的 *日志观察器工厂*。假设有一个名为 my.py
的文件,其中包含以下代码
from twisted.logger import textFileLogObserver
def logger():
return textFileLogObserver(open("/tmp/my.log", "w"))
调用 twistd --logger my.logger ...
将把日志记录到名为 /tmp/my.log
的文件中(这个简单的示例可以很容易地用 --logfile
参数替换)。
或者,可以通过 .tac
文件中可访问的 API 来自定义日志记录行为。 ILogObserver
组件可以设置在应用程序上,以自定义 twistd
将使用的默认日志观察器。
以下是如何使用 DailyLogFile
的示例,它每天轮换一次日志。
from twisted.application.service import Application
from twisted.logger import ILogObserver, textFileLogObserver
from twisted.python.logfile import DailyLogFile
application = Application("myapp")
logfile = DailyLogFile("my.log", "/tmp")
application.setComponent(ILogObserver, textFileLogObserver(logfile))
调用 twistd -y my.tac
将在 /tmp/my.log
创建一个日志文件。
Twisted 提供的服务¶
Twisted 还为常见情况(如监听 TCP 端口)提供了预先编写的 IService
实现,位于 twisted.application.internet
模块中。以下是一个构建在 TCP 端口 7001 上运行回声服务器的服务的简单示例
from twisted.application import internet, service
from somemodule import EchoFactory
port = 7001
factory = EchoFactory()
echoService = internet.TCPServer(port, factory) # create the service
这些服务中的每一个(除了 TimerService)在反应器上都有一个相应的“连接”或“监听”方法,并且服务的构造函数接受与反应器方法相同的参数。“连接”方法用于客户端,“监听”方法用于服务器。例如,TCPServer
对应于 reactor.listenTCP
,TCPClient
对应于 reactor.connectTCP
。
TCPServer
TCPClient
允许您在 TCP 端口上建立连接和监听连接的服务。
UNIXServer
UNIXClient
在 UNIX 套接字上监听和建立连接的服务。
SSLServer
SSLClient
允许您建立 SSL 连接和运行 SSL 服务器的服务。
UDPServer
UNIXDatagramServer
UNIXDatagramClient
在 UNIX 数据报套接字上发送和接收数据的服务。
MulticastServer
支持多播的 UDP 套接字方法的服务器。
TimerService
定期调用函数的服务。
服务集合¶
IServiceCollection
对象包含 IService
对象。可以通过调用 setServiceParent
将 IService 对象添加到 IServiceCollection,并使用 disownServiceParent
将其分离。
IServiceCollection 的标准实现是 MultiService
,它也实现了 IService。MultiService 用于创建一个新的服务,该服务组合了两个或多个现有服务。例如,您可以创建一个 DNS 服务作为 MultiService,它有两个子服务:TCP 服务和 UDP 服务。
from twisted.application import internet, service
from twisted.names import server, dns, hosts
port = 53
# Create a MultiService, and hook up a TCPServer and a UDPServer to it as
# children.
dnsService = service.MultiService()
hostsResolver = hosts.Resolver('/etc/hosts')
tcpFactory = server.DNSServerFactory([hostsResolver])
internet.TCPServer(port, tcpFactory).setServiceParent(dnsService)
udpFactory = dns.DNSDatagramProtocol(tcpFactory)
internet.UDPServer(port, udpFactory).setServiceParent(dnsService)
# Create an application as normal
application = service.Application("DNSExample")
# Connect our MultiService to the application, just like a normal service.
dnsService.setServiceParent(application)