Twisted服务器开发技巧(3) - 动态配置加载
1. Twisted服务器开发技巧(3) - 动态配置加载
我们经常去做配置文件的更改,BSDer们常常需要在配置文件更改后重新启动daemon。这样的服务很多,比如apache。有一天我忽然羡慕起破烂的tomcat来,原因很简单,它的配置文件更改后,不再需要我去重新启动它了。其实,你只需要在性能和功能间寻找一个平衡点,所有的功能都能做到,只是你是否考虑负载的能力。twisted考虑到了动态加载这样的功能,就是在指定的时间去做一件事,但是为了让这样的功能不去影响性能,最好的办法是将这样的时间调度不使用阻塞的sleep,而使用事件的queue再进行调度。
以下是一个示例,只为运行,最终的代码肯定不会有这么糟糕的使用方法:
1 from twisted.application import internet, service
2 from twisted.internet import protocol, reactor, defer
3 from twisted.protocols import basic
4
5 class FingerProtocol(basic.LineReceiver):
6 def lineReceived(self, user):
7 self.factory.getUser(user
8 ).addErrback(lambda _: "Internal error in server"
9 ).addCallback(lambda m:
10 (self.transport.write(m+"\r\n"),
11 self.transport.loseConnection()))
12
13 class FingerService(service.Service):
14 def __init__(self, filename):
15 self.users = {}
16 self.filename = filename
17 def _read(self):
18 for line in file(self.filename):
19 user, status = line.split(':', 1)
20 user = user.strip()
21 status = status.strip()
22 self.users[user] = status
23 self.call = reactor.callLater(30, self._read)
24 def startService(self):
25 self._read()
26 service.Service.startService(self)
27 def stopService(self):
28 service.Service.stopService(self)
29 self.call.cancel()
30 def getUser(self, user):
31 return defer.succeed(self.users.get(user, "No such user"))
32 def getFingerFactory(self):
33 f = protocol.ServerFactory()
34 f.protocol, f.getUser = FingerProtocol, self.getUser
35 return f
36
37 application = service.Application('finger', uid=1000, gid=1)
38 f = FingerService('/etc/users')
39 finger = internet.TCPServer(79, f.getFingerFactory())
40
41 finger.setServiceParent(service.IServiceCollection(application))
42 f.setServiceParent(service.IServiceCollection(application))
这段代码主要是说明了factory的深入使用。init方法中只是初始化好了变量。这个与我们以前的使用没有什么两样,但是在startService和stopService中加了两句话。
self._read()
调用了_read()方法,它初始的读了/etc/users文件到内存变量中。并使用
self.call = reactor.callLater(30, self._read)
向核心调度器加入了30秒后再执行本方法。从而达到了循环不间断的调用_read方法。
而stopService中的
self.call.cancel()
语句,则在停止服务器,从核心调度器的queue中取消了本方法的调用。
准确的说,如果你希望为服务加入一系列的基本的固定周期的事务,哪么使用这样的技巧来将它们加入到核心调度器中去罢。而不要启动单独的线程加入sleep来操作,要知道twisted会更有效的使用调度机制,损耗只会更小。