介绍了如何将前面的server产品化、daemonlogie化(按我的理解就是自己可以在后台长期平稳运行,不需要terminal、人工干预)
IService Interface: 定义了一个named service ,可以使这个service开始和停止。service 所做的就是提供了一些通用的属性和方法。
两个必须的属性:name 和 running。name是string或者为None,runing 是一个布尔值,为True表示这个service 已经成功的开始了。
stopService可能会返回一个deffered,这样的deffered应该在service完全关闭的时候被fire,这样可以让我们的service 在整个应用结束之前完成清理手尾的工作。如果返回None, service就会马上关闭。
IServiceCollection Interface:多个service可以被放在一起形成一个collection,在collection里面的所有service同时开始和停止。 IService 的setServiceParent, 可以将一个Service添加到一个colection。 service可以有parent,也就是意味着它们可以形成层级。这就带出了IServiceCollection的概念:定义了一个可以包含多个IService object的object。提供了getServinceNamed(根据name来查找一个service);遍历里面所有的service__iter__), addService(添加一个service到collection),removeService
Application Interface: 实际不是单独定义的一个interface,一个Application oject必须同时实现IService和IServiceCollection,初次之外,还一些其他的interface(本章没有涉及到)。一个Application 是整个twisted 应用的最高层的service,其他的所有Daemon里面的service都是它的子孙。一般不需要自己实现Application,twisted提供现成的实现,可以直接使用。
twisted 的tac file: 就是twisted的环境配置文件,代表了一个特定的布局,记录的是例如端口号、文件路径等信息。
twisted plugin system:tac file 让我们在配置server的时候有很大的灵活性,但有时候我们并不需要这么多的灵活性,有时候可配置的选项很少,为每一种配置都弄一个tac file显得太麻烦了,如果可以在twisted 命令行直接指定这些选项就很方便,twisted的plugin 系统就提供了这样的可能。
IPlugin Interface: 实际上,这个interace没有指定任何方法,实现IPlugin只是意味着这是一个plugin,让twisted可以找到它。当然,要让plugin 有实际用处,它还必须实现其他的interface。
IServiceMaker interface:一个实现了IServiceMake的object知道如何创建一个IService。
第十八章
有时候,我们需要并行的运行一组异步的操作,因为twisted 是单线程的,所以它们不会真正的并行,重点是
我们需要在同一个组多个任务中使用异步I/O来尽可能快的工作,那么我们怎么知道所有已经开始的一部操作都
已经完成了呢?twisted提供了这样的一中抽象,用来帮助解决这个问题: The Deffered List。
一个DefferedList 是从一个python list创建的,这个python list 里面的每一个元素必须是Deffered Object。
DefferedList 本身也是一个deffered(它继承自Deffered), 这意味着你可以添加callback和errback,就像
普通的deffered一样。
如果用来构建DefferedList的list是空的,那么Deffered的callback会在被添加的时候马上被fired。
deffered list 的结果也是一个list,list 里面的每个元素是一个2元素的tuple: (is_success, res)
is_success:布尔量, res 是deffered list 里面的deffered 的结果;返回的list里面,结果的顺序跟
deffered list 里面deffered 的顺序是对应的。
如果DefferedList里面的deffered 不为空,那么在所有的deffered都被fired之后,它自身才会被fired,
也就是说这是它的callback/errback才会被调用。如果为空,那么DefferedList会被马上fired,因为
它不用等待任何的deffered被fired。
DefferedList永远不会fail,因为deffered list里面所有的result 都会被收集(不管是result还是Failure)
DefferedList的构造函数中,consumeErrors参数的作用:DefferedList需要知道它里面的每一个deffered
何时被fire,它通过通过在每个deffered里面添加一个callback和errback来做到。默认的情况,callback
和errback都是返回原来的result/failure的。所以,如果某个deffered的最后一步失败了,并且返回的是
一个failue并且作为DefferedList添加的这个errback的参数,而这个errback前面说过了,它只是简单的返回
自己接收到的这个failue,所以就出现了一个没有被处理的failue,会报错。如果把comsumeError设置为
True,那么DefferList添加的这个errback会返回一个None,这样相当是把接收到的failure comsume 了。
第十七章:
介绍了除了defer之外,另外一种组织和管理callback的方法:inlineCallbacks
1、inlineCallbacks 是一个decorator,它可以把一个generator函数(使用了yield语句的函数)变成是一系列的异步callbacks的调用。
2、调用decoratored by inlineCallbacks 的函数的时候,我们不需要调用send、next等函数把yield的结果发送给generator,inlineCallbacks负责这一切,保证generator可以顺利跑完(前提是generator本身不抛异常)
3、如果yield的是defer,那么generator会暂停,直到返回的defer被fired。如果defer是success的,则返回defer的结果,否则,就抛异常(普通的Exception,而不是Failue)
@inlineCallbacks
def some_func():
res1 = yield ...
res2 = yield ..
defer.returnValue(res2)
d = some_func()
d.addCallback(func1)
d.addBoth(func2)
经过inlineCallBacks的修饰,some_funct() 返回的是一个deffer,调用者只需要往这个defer添加callback/errback, 剩下的事情就由inlineCallBacks和some_func来协调完成。注意,返回的defer并不是yield 的defer,这个返回的defer仅当generator运行完或者抛一个异常的时候,才会被fired。
some_func里面有三种跟inlineCallBacks会产生互动的语句:
1、yield some_expr
如果yield 的是common value(就是不是defer),那么会直接返回给yield左边的表达式,a = yield b 相当于 a = b; 如果yield的是defer,那么inlineCallback会保证yield 表达式的值(如res1 )会得到defer被fired的时候的结果(res or err)
2、defer.returnVale(some_val)
实际上是带着some_val 的异常,这个异常被inlineCallbacks捕捉,然后some_val作为defer的结果用来fired 这个difer:defer.callback(some_value)
3、最后没有使用returnValue() 来返回值,到了some_func执行完
inlineCallback会捕获一个StopIteration(表示一个generator执行到了the end of function),此时对于some_func来说,是没有值返回的,所以在inlineCallbacks里面,就会调用deffer.callback(None),然后返回defer。
4、抛其他的异常
inlineCallbacks会调用deffer.errback()
让some_func从头跑到尾的前提是:some_func本身不抛异常
使用inlineCallbacks的好处:
1、所有的callbacks都共享一个namespace,所以不用传递额外的状态
2、callback的顺序很容易看得出,就是从上到下
3、节省打字:不用定义独立的callback function,隐含了的flow-control
4、错误处理可以用熟悉的try/except 语句
缺点:
generator里面的callbacks不能单独的被调用,造成了代码不易重用
看起来像同步编程的形式容易让实际是异步的function 在被调用的事实被隐藏起来。