【IT168 技术】作者在开发中遇到了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 http://localhost:8000in 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()
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