11

Herokuで実行されるDjangoadminからのモデルからのデータを含むcsvファイルをエクスポートする必要があります。したがって、csvを作成して応答で返すアクションを作成しました。これは、クライアントが膨大なデータセットのエクスポートを開始し、Webワーカーの30秒のタイムアウトが発生するまで正常に機能しました。

この問題を回避するために、最初にメモリに作成して1つにまとめて送信するのではなく、クライアントにcsvをストリーミングすることを検討しました。トリガーはこの情報でした:

Cedarは、ロングポーリングおよびストリーミング応答をサポートします。アプリには、クライアントに1バイトで応答するための最初の30秒のウィンドウがあります。各バイトが送信された後(クライアントから受信された、またはアプリケーションによって送信された)、55秒のローリングウィンドウをリセットします。> 55秒のウィンドウ中にデータが送信されない場合、接続は終了します。

したがって、次のようなものを実装してテストしました。

import cStringIO as StringIO
import csv, time

def csv(request):
    csvfile = StringIO.StringIO()
    csvwriter = csv.writer(csvfile)

def read_and_flush():
    csvfile.seek(0)
    data = csvfile.read()
    csvfile.seek(0)
    csvfile.truncate()
    return data

def data():
    for i in xrange(100000):
        csvwriter.writerow([i,"a","b","c"])
        time.sleep(1)
        data = read_and_flush()
        yield data

response = HttpResponse(data(), mimetype="text/csv")
response["Content-Disposition"] = "attachment; filename=test.csv"
return response

ダウンロードのHTTPヘッダーは次のようになります(FireBugから):

HTTP/1.1 200 OK
Cache-Control: max-age=0
Content-Disposition: attachment; filename=jobentity-job2.csv
Content-Type: text/csv
Date: Tue, 27 Nov 2012 13:56:42 GMT
Expires: Tue, 27 Nov 2012 13:56:41 GMT
Last-Modified: Tue, 27 Nov 2012 13:56:41 GMT
Server: gunicorn/0.14.6
Vary: Cookie
Transfer-Encoding: chunked
Connection: keep-alive

「Transfer-encoding:chunked」は、Cedarが実際にコンテンツをチャンク単位でストリーミングしていることを示します。

問題は、Herokuログの次の行で30秒後もcsvのダウンロードが中断されることです。

2012-11-27T13:00:24+00:00 app[web.1]: DEBUG: exporting tasks in csv-stream for job id: 56, 
2012-11-27T13:00:54+00:00 app[web.1]: 2012-11-27 13:00:54 [2] [CRITICAL] WORKER TIMEOUT (pid:5)
2012-11-27T13:00:54+00:00 heroku[router]: at=info method=POST path=/admin/jobentity/ host=myapp.herokuapp.com fwd= dyno=web.1 queue=0 wait=0ms connect=2ms service=29480ms status=200 bytes=51092
2012-11-27T13:00:54+00:00 app[web.1]: 2012-11-27 13:00:54 [2] [CRITICAL] WORKER TIMEOUT (pid:5)
2012-11-27T13:00:54+00:00 app[web.1]: 2012-11-27 13:00:54 [12] [INFO] Booting worker with pid: 12

これは概念的には機能するはずですよね?見逃したことはありますか?

本当にありがとうございました。トム

4

2 に答える 2

10

私はその問題の解決策を見つけました。HerokuログにH12タイムアウトが発生するため、Herokuタイムアウトではありません(これを指摘してくれたHerokuのCaioに感謝します)。

問題は、Gunicornのデフォルトのタイムアウトが30秒であるということでした。Procfile(Gunicornの行)に--timeout 600を追加した後、問題はなくなりました。

Procfileは次のようになります。

web: gunicorn myapp.wsgi -b 0.0.0.0:$PORT --timeout 600
celeryd: python manage.py celeryd -E -B --loglevel=INFO
于 2012-11-30T08:39:21.573 に答える
1

これはスクリプトの問題ではなく、30秒のWebリクエストのデフォルトのHerokuタイムアウトの問題です。これを読むことができます: https ://devcenter.heroku.com/articles/request-timeout そしてこのドキュメントによると-CSVエクスポートをバックグラウンドプロセスに移動します。

于 2012-11-27T18:10:20.240 に答える