chúng tôi có nhu cầu xuất tệp csv bao gồm dữ liệu từ mô hình từ quản trị viên Django chạy trên Heroku. Do đó, chúng tôi đã tạo một hành động mà chúng tôi đã tạo csv và trả lại trong phản hồi. Điều này làm việc tốt cho đến khi khách hàng của chúng tôi bắt đầu xuất dữ liệu khổng lồ và chúng tôi chạy vào thời gian chờ 30 giây của nhân viên Web.Xuất CSV trong luồng (từ quản trị Django trên Heroku)
Để tránh sự cố này, chúng tôi đã nghĩ về việc truyền trực tuyến csv cho ứng dụng khách thay vì xây dựng nó trước tiên trong bộ nhớ và gửi nó thành một phần. Trình kích hoạt là phần thông tin này:
Cedar hỗ trợ phản hồi bỏ phiếu và phát trực tiếp. Ứng dụng của bạn có cửa sổ thứ hai 30 giây đầu tiên để phản hồi bằng một byte đơn trở lại ứng dụng khách. Sau mỗi byte được gửi (hoặc nhận được từ máy khách hoặc được gửi bởi ứng dụng của bạn), bạn thiết lập lại một cửa sổ 55 giây. Nếu không có dữ liệu nào được gửi trong cửa sổ thứ 55 thì kết nối của bạn sẽ bị chấm dứt.
Do đó chúng tôi thực hiện cái gì đó trông như thế này để kiểm tra nó:
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
Phần header HTTP của việc tải xuống trông như thế này (từ 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
"Chuyển mã hóa : chunked "sẽ chỉ ra rằng Cedar thực sự đang truyền tải nội dung một cách chunkwise chúng tôi đoán.
Vấn đề là việc tải xuống của csv vẫn bị gián đoạn sau 30 giây với những dòng này trong nhật ký Heroku:
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
này nên làm việc về mặt khái niệm, phải không? Có bất cứ điều gì chúng tôi bị mất?
Chúng tôi thực sự đánh giá cao sự trợ giúp của bạn. Tom
Nhưng nên cửa sổ 30 timeout thứ hai không thể kéo dài bởi vì chúng tôi dòng nội dung thay vì chờ cho đến khi csv đã được tạo ra trong bộ nhớ? Vì vậy, có các byte được truyền trong cửa sổ 30 giây này và điều này sẽ tránh thời gian chờ theo như sau: Cedar hỗ trợ các tính năng HTTP 1.1 chẳng hạn như phản hồi và phát trực tuyến dài. Một ứng dụng có một cửa sổ ban đầu 30 giây để phản hồi với một byte đơn trở lại máy khách. Tuy nhiên, mỗi byte truyền sau đó đặt lại một cửa sổ 55 giây. – Tom
Có thể nào là Django có thời gian chờ nội bộ khi gửi phản hồi? – Tom
Bạn có yêu cầu web của bạn hoạt động trong hơn 30 giây - đó là sự thật và Heroku có thời gian chờ mặc định là 30 giây đối với bất kỳ yêu cầu web nào trong cấu hình máy chủ http của nó. Tôi cho rằng, những cố gắng của bạn để mô phỏng phiên giao tiếp sẽ không thành công - bạn nên xem xét việc chuyển tệp xử lý dài của mình sang nền/daemon nền. – moonsly