9

大規模な CSV 応答を作成する Perl モジュールのセクションで作業しています。サーバーは Plack で実行されますが、これについては私は専門家ではありません。

現在、私は次のようなものを使用して応答を送信しています:

$res->content_type('text/csv');
my $body = '';
query_data (
    parameters  => \%query_parameters,
    callback    => sub {
        my $row_object = shift;
        $body .= $row_object->to_csv;
    },
);
$res->body($body);
return $res->finalize;

ただし、そのquery_data関数は高速ではなく、多くのレコードを取得します。そこでは、各行を連結し$body、すべての行が処理された後、応答全体を送信しています。

私がこれを好まない理由は 2 つあります。1 つ目は、$bodyが破棄されるまで大量の RAM を消費することです。第 2 に、そのメソッドが動作を終了し、実際に$res->body($body).

必要なものを見つけずに、ドキュメントでこれに対する答えを見つけようとしました。

また$res->body($row_object->to_csv)、コールバック セクションを呼び出してみましたが、最後に行った呼び出しのみを送信し$res->body、以前の呼び出しをすべて上書きしてしまうようです。

各行のコンテンツをフラッシュするPlack応答を送信する方法はありますか?そのため、ユーザーはデータが収集されるとリアルタイムでコンテンツを受信し始め、最初にすべてのデータを蓄積する必要はありませんか?

コメントをお寄せいただきありがとうございます。

4

3 に答える 3

2

Plack::Responseを使用することはできません。そのクラスは完全な応答を表すことを目的としており、一度にメモリ内に完全な応答を保持することは決してないからです。あなたがやろうとしていることはストリーミングと呼ばれ、Plack::Response がサポートしていなくても、 PSGI はそれをサポートしています。

これを実装する方法は次のとおりです(サンプルコードから適応):

my $env = shift;

if (!$env->{'psgi.streaming'}) {
    # do something else...
}

# Immediately start the response and stream the content.
return sub {
    my $responder = shift;
    my $writer = $responder->([200, ['Content-Type' => 'text/csv']]);

    query_data(
        parameters  => \%query_parameters,
        callback    => sub {
            my $row_object = shift;
            $writer->write($row_object->to_csv);
            # TODO: Need to call $writer->close() when there is no more data.
        },
    );
};

このコードに関するいくつかの興味深い点:

  • Plack::Responseオブジェクトを返す代わりに、 を返すことができますsub。このサブルーチンは、実際の応答を取得するためにしばらくしてから呼び出されます。PSGI はこれをサポートして、いわゆる「遅延」応答を可能にします。
  • 返されるサブルーチンは、呼び出して実際の応答を渡す必要がある引数coderef(この場合は) を取得します。$responder実際の応答に「本文」(つまり、通常は の 3 番目の要素arrayref)が含まれていない場合、$responderは本文を書き込むことができるオブジェクトを返します。PSGI はこれをサポートして、ストリーミング応答を可能にします。
  • この$writerオブジェクトには 2 つのメソッドがwriteあり、closeどちらもその名前が示すとおりに機能します。closeメソッドを呼び出して応答を完了することを忘れないでください。上記のコードはこれを示していません。これを呼び出す方法はquery_data、他のコードがどのように機能するかに依存するためです。
  • ほとんどのサーバーは、このようなストリーミングをサポートしています。あなたのものがそうであることを確認$env->{'psgi.streaming'}することができます。
于 2017-01-03T20:41:41.583 に答える
-1

Plack はミドルウェアです。その上で Mojolicious や Dancer2 などの Web アプリケーション フレームワークを使用していますか、それともその下で Apache や Starman サーバーなどを使用していますか? これは、バッファリングの仕組みに影響します。

上記のリンクは、Plack の作成者による例を示しています: https://metacpan.org/source/MIYAGAWA/Plack-1.0037/eg/dot-psgi/echo-stream-sync.psgi

または、Plack と Starman または Apache の上で Dancer2 を使用して簡単に実行できます: https://metacpan.org/pod/distribution/Dancer2/lib/Dancer2/Manual.pod#Delayed-responses-Async-Streaming

よろしく、ピーター

于 2016-10-27T09:13:35.637 に答える
-2

あなたのためのいくつかの読み物:)

したがって、コピー/貼り付け/適応して報告してください

于 2015-07-31T00:51:09.963 に答える