7

が提供する API はgevent.http.HTTPServer、双方向のストリーミングをサポートしているようです。リクエスト オブジェクトは、リクエスト ボディを単純な文字列として提供するのではなく、代わりに.input_bufferPython の反復可能な属性を提供します。一方、他の方向では、レスポンスのデータを 3 つの呼び出しでチャンクとして配信できます。

request.send_reply_start(200, 'OK')
request.send_reply_chunk(...)  # as many times as you wish
request.send_reply_end()

しかし、この驚くほどバッファリングされていない API にもかかわらず、リクエスト POST データの最後のチャンクが最終的に到着するまでリクエスト ハンドラーが呼び出されず、他の方向でクライアントにヘッダーが到着していないため、何かが誤って設定されている必要があります。サーバーが到達するまでソケット.send_reply_end()。バッファリングをオフにしてリクエストを確認し、到着時に応答を送信するために、スローする必要があるスイッチまたは操作する必要がある構成設定がありますStreamServerか?

私のアプリケーションは、RAM よりも大きい可能性のある単一ファイルのアップロードとダウンロードをサポートする必要があるため、このバッファリングをオフにする必要があります。

以下は、gevent で記述された単純なサーバーとクライアントで、この動作を示すはずです。

# srv.py

import gevent.http

M100 = 100 * 1024 * 1024

def main():
    print 'Serving on 8088...'
    gevent.http.HTTPServer(('0.0.0.0', 8088), handle).serve_forever()

def handle(request):
    print 'Is request chunked?', request.chunked
    for item in request.input_buffer:
        print 'received body segment of length', len(item), 'bytes'
    request.add_output_header('Content-Type', 'application/octet-stream')
    request.send_reply_start(200, 'OK')
    for i in range(5):
        print 'sending chunk', i
        request.send_reply_chunk(M100 * 'x')
    request.send_reply_end()

if __name__ == '__main__':
    main()

と:

# cli.py

import requests
import time

M100 = 100 * 1024 * 1024

def gen():
    for i in range(5):
        print 'sending chunk', i
        yield M100 * 'x'
        time.sleep(1)

if __name__ == '__main__':
    r = requests.post('http://localhost:8088/', data=gen(), stream=True)
    for block in r.iter_content(M100):
        print 'received', len(block), 'bytes from download'

ご指導ありがとうございます。

4

1 に答える 1

0

サーバーへのリクエスト:ソース コードを見ると、チャンク方式で送信されるかどうかに関係なく、リクエストが完了するまでサーバーのハンドラー関数が呼び出されないように見えます。だからあなたはそこで運が悪いです。

サーバーの応答:サーバーの応答はストリーミング形式で送信できますが、これを機能させるには、ハンドラー スレッドで自発的に制御を渡す必要があります (たとえば、gevent.sleep()各チャンクの後に呼び出すなど)。

残念ながら、gevent次のチャンクを開始する前に特定のチャンクの送信が完了するのを待つ方法を提供していないようです。そのため、送信できるよりも速くデータを生成すると、メモリの問題が発生する可能性があります。


上記の情報は、ライブラリgevent<1.0を使用するに関するものでありlibevent、より新しいバージョンの には適用されないことに注意してくださいgevent。の現在のバージョンにはモジュールが含まれていないため、質問は意味がありgeventません。http

于 2016-09-07T07:54:31.993 に答える