2012-10-24 28 views
10

Tôi đang cố gắng đặt giới hạn tốc độ khi tải xuống/tải lên tệp và thấy rằng xoắn cung cấp twisted.protocols.policies.ThrottlingFactory để xử lý công việc này, nhưng tôi không thể làm đúng. Tôi đặt readLimitwriteLimit nhưng tệp vẫn tải xuống ở tốc độ tối đa. Tôi đang làm gì sai?Điều chỉnh băng thông bằng cách sử dụng Twisted

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() 

CẬP NHẬT

Vì vậy, đôi khi sau khi tôi chạy nó:

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' 

tôi thấy rằng tôi không được phép chuyển nhượng nhà sản xuất như tôi biết tsite.protocol.producer = producer, Tôi mới đến Xoắn và tôi không biết làm thế nào để làm điều đó theo một cách khác.

+1

Nhìn vào nguồn có một dòng, 'lo g.msg ("Điều chỉnh lượt đọc trên% s"% tự) 'bạn có thể xác minh rằng điều này đang được ghi lại không? – John

+0

nó không đăng nhập * throttleReads phương pháp, nhưng nó * throttleWrites: 'Throttling viết trên ' –

+0

Tôi nghĩ bạn phải chèn đối tượng Throttling hoặc giữa 'tập tin' đọc và và 'render()', hoặc có lẽ tốt hơn giữa 'reactor' và' render/DownloadPage instance' của bạn. Ngay bây giờ bạn dường như truyền 'producer' cho cả hai đối tượng DownloadPage và Throttling, điều này có vẻ không đúng. –

Trả lời

1

Every producer needs (eventually) to be registered with whatever you want to consume the data. Tôi không thấy đăng ký diễn ra ở bất cứ nơi nào ở đây. Có lẽ đó là vấn đề bạn đang gặp phải? Twisted đã được sử dụng trên một số dự án lớn như Friendster, nhưng tất cả các callbacks không ngồi tốt với cách thông thường tôi viết bằng python (và tôi có một số kinh nghiệm với lập trình chức năng). Tôi đã chuyển sang gevent.

Nếu bạn đang làm việc với thư viện gevent, nhiều chi tiết (callbacks/generator cung cấp chức năng không đồng bộ) được trừu tượng hóa, để bạn có thể lấy đi bằng cách chỉ khỉ vá mã của bạn và viết nó vào đối tượng thông thường định hướng theo phong cách mà bạn quen thuộc. Nếu bạn đang làm việc trên một dự án với bất cứ ai không quen thuộc với một ngôn ngữ gọi lại nặng như js/lisp, tôi đặt cược họ sẽ đánh giá cao gevent qua xoắn.

+0

Câu trả lời này sẽ tốt hơn (xứng đáng với một upvote) mà không có sự bắn tỉa vô nghĩa. Bạn thậm chí không đề cập đến cách gevent giao dịch với kiểm soát dòng chảy. – Glyph

+0

@Glyph thực sự xin lỗi về điều đó - hy vọng tôi đã loại bỏ sự hận thù. Tấn tôn trọng những người (rực rỡ) đã phát triển Twisted - tôi có nghĩa là không có hành vi phạm tội. Có lẽ chỉ là một số vết sẹo còn lại từ kinh nghiệm xấu của tôi. :) – egbutter

+0

Cảm ơn bạn đã thay đổi nó - nhưng bạn vẫn không giải thích cách gevent thực sự xử lý vấn đề cụ thể về điều khiển luồng :). – Glyph

1

egbutter cho biết, bạn phải đăng ký một nhà sản xuất. Vì vậy, thay vì điều này:

tsite.protocol.producer = producer 

bạn phải gọi một phương phápregisterProducer một cách rõ ràng:

tsite.protocol.registerProducer(...) 

hoặc, nếu bạn đang sử dụng FileSender như một nhà sản xuất, hãy gọi beginFileTransfer phương pháp của nó , trong trường hợp của chúng tôi:

file_to_send = open(...) 
producer.beginFileTransfer(file_to_send, tsite.protocol) 
Các vấn đề liên quan