在开发中 遇到了twisted web中实现了异步的情况,按照通常的方法,行不通,查了下资料。正确的做法如下:
Here is an example with resources adapted from the Abe
Fettig example on page 48 of "Twisted Network
Programming Essentials." I am still getting my feet
wet with resources. I intend to use this to help
prototype REST support in WS-BPEL.
Asynchronous Responses
In all of the Twisted web server examples up to this point, we have assumed that the
server can instantaneously respond to clients without having to first retrieve an expen‐
sive resource (say, from a database query) or do expensive computation. What happens
when responding to a request blocks?
Example 4-9implements a dummy BusyPageresource that sleeps for five seconds before
returning a response to the request.
Example 4-9. blocking.py
-
from twisted.internet import reactor
-
from twisted.web.resource import Resource
-
-
from twisted.web.server import Site
-
import time
-
class BusyPage(Resource):
-
isLeaf = True
-
def render_GET(self, request):
-
time.sleep(5)
-
return "Finally done, at %s" % (time.asctime(),)
-
factory = Site(BusyPage())
-
reactor.listenTCP(8000, factory)
-
reactor.run()
If you run this server and then load several browser tabs in quick
succession, you’ll observe that the last page to load will load N*5 seconds after the first
page request, where N is the number of requests to the server. In other words, the
requests are processed serially.
This is terrible performance! We need our web server to be responding to other requests
while an expensive resource is being processed.
One of the great properties of this asynchronous framework is that we can achieve the
responsiveness that we want without introducing threads by using the Deferred API
we already know and love.
Example 4-10demonstrates how to use a Deferredinstead of blocking on an expensive
resource. deferLaterreplaces the blocking time.sleep(5)with a Deferred that will
fire after five seconds, with a callback to _delayedRenderto finish the request when the
fake resource becomes available. Then, instead of waiting on that resource, render_GET
returns NOT_DONE_YETimmediately, freeing up the web server to process other requests.
Example 4-10. non_blocking.py
-
from twisted.internet import reactor
-
from twisted.internet.task import deferLater
-
from twisted.web.resource import Resource
-
from twisted.web.server import Site, NOT_DONE_YET
-
import time
-
class BusyPage(Resource):
-
isLeaf = True
-
def _delayedRender(self, request):
-
request.write("Finally done, at %s" % (time.asctime(),))
-
request.finish()
-
-
def render_GET(self, request):
-
d = deferLater(reactor, 5, lambda: request)
-
d.addCallback(self._delayedRender)
-
return NOT_DONE_YET
-
-
factory = Site(BusyPage())
-
reactor.listenTCP(8000, factory)
-
reactor.run()
####################################################################
以下代码案例来之
这里
-
class HomePage(resource.Resource):
-
-
def doWork(self):
-
message = """
-
<html>
-
<head>
-
</head>
-
<body>
-
Hello World
-
</body>
-
</html>
-
"""
-
self.request.write(message)
-
self.request.finish()
-
-
-
def render(self, request):
-
self.request = request
-
stackless.tasklet(self.doWork)()
-
return server.NOT_DONE_YET
and here is one with PyAMF .2
class EchoServer(TwistedGateway):
def __init__(self):
super(EchoServer, self).__init__()
self.request = None
return
def __echo__(self, request, deferred, y):
print "=>", request, deferred, y
deferred.callback(y)
def echo(self, request, y):
print "=>", request, y
deferred = defer.Deferred()
stackless.tasklet(self.__echo__)(request,deferred, y)
return deferred
##############################################################################################
补充: 用twisted来做web开发很不方便,推荐用另外一个基于twisted和tornado实现的web框架cyclone 。
包括本文所提到的异步问题,实现起来也相当简单。
再次放一个cyclone实现的web异步小demo代码
from twisted.internet import reactor
class MyRequestHandler(web.RequestHandler):
@web.asynchronous
def get(self):
self.write("Processing your request...")
reactor.callLater(5, self.do_something)
def do_something(self):
self.finish("done!")
客户端请求一次,服务器可返回多次。
阅读(4485) | 评论(0) | 转发(0) |