2012-10-24 79 views
10

我試圖設置下載/上傳文件的速度限制,發現扭曲提供twisted.protocols.policies.ThrottlingFactory來處理這項工作,但我無法正確理解。我設置了readLimitwriteLimit,但文件仍在以最大速度下載。我究竟做錯了什麼?使用扭曲的帶寬限制

from twisted.protocols.basic import FileSender 
from twisted.protocols.policies import ThrottlingFactory 
from twisted.web import server, resource 
from twisted.internet import reactor 
import os 

class DownloadPage(resource.Resource): 
    isLeaf = True 

    def __init__(self, producer): 
     self.producer = producer 

    def render(self, request): 
     size = os.stat(somefile).st_size 
     request.setHeader('Content-Type', 'application/octet-stream') 
     request.setHeader('Content-Length', size) 
     request.setHeader('Content-Disposition', 'attachment; filename="' + somefile + '"') 
     request.setHeader('Accept-Ranges', 'bytes') 

     fp = open(somefile, 'rb') 
     d = self.producer.beginFileTransfer(fp, request) 

     def err(error): 
      print "error %s", error 

     def cbFinished(ignored): 
      fp.close() 
      request.finish() 
     d.addErrback(err).addCallback(cbFinished) 

     return server.NOT_DONE_YET 


producer = FileSender() 
root_resource = resource.Resource() 
root_resource.putChild('download', DownloadPage(producer)) 
site = server.Site(root_resource) 
tsite = ThrottlingFactory(site, readLimit=10000, writeLimit=10000) 
tsite.protocol.producer = producer 
reactor.listenTCP(8080, tsite) 
reactor.run() 

UPDATE

所以一段時間後我運行它:

2012-10-25 09:17:03+0600 [-] Unhandled Error 
Traceback (most recent call last): 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/application/app.py", line 402, in startReactor 
     self.config, oldstdout, oldstderr, self.profiler, reactor) 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/application/app.py", line 323, in runReactorWithLogging 
     reactor.run() 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1169, in run 
     self.mainLoop() 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1178, in mainLoop 
     self.runUntilCurrent() 
    --- <exception caught here> --- 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/internet/base.py", line 800, in runUntilCurrent 
     call.func(*call.args, **call.kw) 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/protocols/policies.py", line 334, in unthrottleWrites 
     p.unthrottleWrites() 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/protocols/policies.py", line 225, in unthrottleWrites 
     self.producer.resumeProducing() 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/protocols/basic.py", line 919, in resumeProducing 
     self.consumer.unregisterProducer() 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/web/http.py", line 811, in unregisterProducer 
     self.transport.unregisterProducer() 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/protocols/policies.py", line 209, in unregisterProducer 
     del self.producer 
    exceptions.AttributeError: ThrottlingProtocol instance has no attribute 'producer' 

我看到,我不應該指定生產商就像我知道tsite.protocol.producer = producer,我是新來的扭曲,我不知道如何做另一種方式。

+1

看着源頭,有一條線「lo g.msg(「節流讀取%s」%self)'你能證實這是記錄嗎? – John

+0

它不記錄* throttleReads方法,但它* throttleWrites: '限制寫入' –

+0

我想你必須在'file'讀取和插入之間插入Throttling對象和'render()',或者''reactor'和'render/DownloadPage實例'之間可能更好。現在你似乎將'producer'傳遞給DownloadPage和Throttling對象,這看起來不正確。 –

回答

1

Every producer needs (eventually) to be registered with whatever you want to consume the data。我在這裏的任何地方都看不到註冊。也許這就是你遇到的問題?

Twisted已經用於一些像Friendster這樣的大型項目,但所有的回調函數都不能和我在python中編寫的常用方式一致(並且我有一些函數式編程經驗)。我切換到gevent

如果你正在使用gevent庫,許多細節(提供異步功能的回調函數/生成器)都被抽象出來,這樣你就可以通過猴子修補你的代碼並將它寫入常用對象面向你習慣的風格。如果你正在與一個不熟悉像js/lisp這樣的回調繁重的語言的人一起開展一個項目,我敢打賭他們會欣賞扭曲的gevent。

+0

如果沒有無意識的狙擊,這個答案會更好(值得高興)。你甚至沒有提到gevent如何處理流量控制。 – Glyph

+0

@Glyph對此真的很抱歉 - 希望我已經消除了sn iness。對開發Twisted的(聰明的)人的尊重 - 我的意思是沒有冒犯。也許只是我不好的經歷中留下的一些傷痕。 :) – egbutter

+0

謝謝你改變它 - 但你仍然不解釋gevent究竟如何處理流量控制的具體問題:)。 – Glyph

1

由於egbutter說,你必須註冊一個製片人。因此,而不是這樣的:

tsite.protocol.producer = producer 

你必須顯式調用registerProducer方法:

tsite.protocol.registerProducer(...) 

,或者,如果你使用FileSender作爲製片人,調用其beginFileTransfer方法,在我們的例子中:

file_to_send = open(...) 
producer.beginFileTransfer(file_to_send, tsite.protocol)