2017-03-28 6 views
0

したがって、私は単純なファイルダウンロードサーバーを実装するためにTornadoを使用します。ここで私は、現在持っているコードです:あなたが見ることができるように、私はbytearrayのにファイルを読み込み、バイトのオブジェクトに変換Tornadoサーバーはリモートクライアントブロックサーバーにファイルを送信します

class downloadHandler(tornado.web.RequestHandler): 
    @tornado.web.asynchronous 
    def get(self): 
     global data 
     self.write(data) 
     self.flush() 
     self.finish() 

def get_buf(path): 
    buf = bytearray(os.path.getsize(path)) 
    with open(path, 'rb') as f: 
     f.readinto(buf) 
    return bytes(buf) 

if __name__ == '__main__': 
    data = get_buf('path/to/file') 
    tornado.options.parse_command_line() 
    app = tornado.web.Application(handlers=[(r"/upgrade", downloadHandler)]) 
    http_server = tornado.httpserver.HTTPServer(app) 
    http_server.listen(options.port) 
    tornado.ioloop.IOLoop.instance().start() 

、これが唯一のサーバを起動する前に一度行われます。私がやることは、リモートクライアントにデータを書き込むことだけです。ファイルサイズは2MBに似ています。私はそれを「包囲」でテストします。クライアントは並行してデータを次々に受け取っているように見えます。

siege http://xxx.xx.xx.xx:8000/upgrade -c5 -r1 
** SIEGE 4.0.2 
** Preparing 5 concurrent users for battle. 
The server is now under siege... 
HTTP/1.1 200 20.22 secs: 1969682 bytes ==> GET /upgrade 
HTTP/1.1 200 34.24 secs: 1969682 bytes ==> GET /upgrade 
HTTP/1.1 200 48.24 secs: 1969682 bytes ==> GET /upgrade 
HTTP/1.1 200 62.24 secs: 1969682 bytes ==> GET /upgrade 
HTTP/1.1 200 76.25 secs: 1969682 bytes ==> GET /upgrade 

私は竜巻の文書を確認し、私は(self.writeを考える))(非ブロッキング呼び出しであり、私はself.flushと呼ばれます。では、サーバーをブロックするのは何ですか?

私はtornado.web.StaticFileHandlerも試しましたが、結果はほぼ同じです。

PS:トルネードは正しいツールですか?そうでない場合は、私のニーズを達成するための他の代替手段は何ですか?

答えて

1

ではなく、一度にすべての、おそらく256キロバイトのチャンクにデータを書き込む試してみてください。

class downloadHandler(tornado.web.RequestHandler): 
    async def get(self): 
     chunk_size = 256 * 1024 
     for i in range(0, len(data), chunk_size): 
      self.write(bytes(data[i:i + chunk_size])) 
      await self.flush() 

     self.finish() 

def get_buf(path): 
    buf = bytearray(os.path.getsize(path)) 
    with open(path, 'rb') as f: 
     f.readinto(buf) 
    return buf 

ライティングチャンクで(それはない「待つ」何)トルネードのIOLoopは、書き込みの間の制御を取り戻すことができますし、いくつかのことを同時に行う。

バイトに変換するのではなく、データをバイトで保存することによって、一部のデータコピーを保存できることに注意してください。

私のコードはPython 3.5+です。 2.7では、次のようにしてください:

@gen.coroutine 
def get(self): 
    chunk_size = 256 * 1024 
    for i in range(0, len(data), chunk_size): 
     self.write(bytes(data[i:i + chunk_size])) 
     yield self.flush() 

    self.finish() 
+0

あなたのソリューションは非常に合理的だと思います。しかし、結果はまだ同じです... – colin

+0

今、私はそれをテストする方法を変更しました。私は複数の「包囲」プロセスを起動し、それぞれがサーバーへの単一の接続を開始し、同時に同時に動作します。 – colin

関連する問題