当URI相同时(来自同一浏览器的多个调用),Twisted deferreds阻塞

时间:2016-10-25 16:28:00

标签: twisted

我有以下代码

# -*- coding: utf-8 -*-

# 好

##########################################

import time
from twisted.internet import reactor, threads
from twisted.web.server import Site, NOT_DONE_YET
from twisted.web.resource import Resource

##########################################

class Website(Resource):
  def getChild(self, name, request):
    return self
  def render(self, request):
    if request.path == "/sleep":
      duration = 3
      if 'duration' in request.args:
        duration = int(request.args['duration'][0])
      message = 'no message'
      if 'message' in request.args:
        message = request.args['message'][0]
      #-------------------------------------
      def deferred_activity():
        print 'starting to wait', message
        time.sleep(duration)
        request.setHeader('Content-Type', 'text/plain; charset=UTF-8')
        request.write(message)
        print 'finished', message
        request.finish()
      #-------------------------------------
      def responseFailed(err, deferred):
        pass; print err.getErrorMessage()
        deferred.cancel()
      #-------------------------------------
      def deferredFailed(err, deferred):
        pass; # print err.getErrorMessage()
      #-------------------------------------
      deferred = threads.deferToThread(deferred_activity)
      deferred.addErrback(deferredFailed, deferred) # will get called indirectly by responseFailed
      request.notifyFinish().addErrback(responseFailed, deferred) # to handle client disconnects
      #-------------------------------------
      return NOT_DONE_YET
    else:
      return 'nothing at', request.path

##########################################

reactor.listenTCP(321, Site(Website()))
print 'starting to serve'
reactor.run()

##########################################
# http://localhost:321/sleep?duration=3&message=test1
# http://localhost:321/sleep?duration=3&message=test2
##########################################

我的问题如下:

当我在浏览器中打开两个标签时,在http://localhost:321/sleep?duration=3&message=test1指向一个,在http://localhost:321/sleep?duration=3&message=test2指向另一个标签(消息不同)并重新加载第一个标签然后尽快完成第二个标签,然后完成几乎完成同时。第一个标签在点击F5后大约3秒钟,第二个标签在第一个标签后大约半秒钟完成。

这是预期的,因为每个请求都被延迟到一个线程中,并且它们并行睡眠。

但是,当我现在将第二个标签的URL更改为与第一个标签的URL相同时,即http://localhost:321/sleep?duration=3&message=test1,则所有这些都会变为阻塞。如果我在第一个选项卡上按F5并在第二个选项卡上尽可能快地按F5,则第二个选项卡在第一个选项卡后约3秒完成。他们不能并行执行。

只要整个URI在两个选项卡中都相同,此服务器就会开始阻止。这在Firefox和Chrome中都是一样的。但是当我同时在Chrome中启动一个和在Firefox中启动另一个时,它再次无阻塞。

所以它可能不一定与Twisted有关,但可能是因为某些连接重用或类似的东西。

任何人都知道这里发生了什么以及如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

巧合的是,有人在龙卷风部分问related question。如您所料,这不是Twisted中的"问题" ,而是Web浏览器的"功能" :)。 Tornado's FAQ page有一小部分专门讨论这个问题。建议的解决方案是附加一个任意查询字符串。

当天的报价:

  

一个开发者的错误是另一个开发人员的无证功能!