Tôi phải giải quyết vấn đề tương tự ngay bây giờ. Nó sẽ không phải là một trang web công cộng, nhưng tương tự, một máy chủ nội bộ với lưu lượng truy cập thấp.
trở ngại kỹ thuật:
- tất cả các dữ liệu đầu vào cho quá trình chạy dài có thể được cung cấp trên bắt đầu của nó
- quá trình chạy dài không yêu cầu tương tác người dùng (trừ đầu vào ban đầu để bắt đầu một quá trình)
- thời gian tính toán đủ dài để kết quả không thể được phục vụ cho khách hàng trong phản hồi HTTP ngay lập tức
- một số loại phản hồi (loại thanh tiến trình) từ quy trình chạy dài.
Do đó, chúng tôi cần ít nhất hai "lượt xem" trên web: một để bắt đầu quá trình chạy dài và quy trình còn lại để theo dõi trạng thái/thu thập kết quả.
Chúng ta cũng cần một số loại thông tin liên lạc interprocess: gửi dữ liệu người dùng từ khởi (web server theo yêu cầu http) đến quá trình chạy dài, và sau đó gửi kết quả của nó đến reciever (một lần nữa web máy chủ, được thúc đẩy bởi các yêu cầu http). Trước đây là dễ dàng, sau này là ít rõ ràng. Không giống như trong lập trình unix bình thường, người nhận không được biết ban đầu. Người nhận có thể là một quá trình khác với người khởi xướng, và nó có thể bắt đầu khi công việc chạy dài vẫn đang được tiến hành hoặc đã kết thúc. Vì vậy, các đường ống không hoạt động và chúng tôi cần một số tính thấm của kết quả của quá trình chạy dài.
tôi thấy hai giải pháp khả thi:
- ra mắt công văn của các quá trình chạy dài để quản lý công việc chạy dài (điều này có lẽ là django-queue-dịch vụ nêu trên là những gì);
- lưu kết quả vĩnh viễn, trong tệp hoặc trong DB.
Tôi thích sử dụng tệp tạm thời và nhớ vị trí của chúng trong dữ liệu phiên. Tôi không nghĩ rằng nó có thể được thực hiện đơn giản hơn.
Một kịch bản công việc (đây là quá trình chạy dài), myjob.py
:
import sys
from time import sleep
i = 0
while i < 1000:
print 'myjob:', i
i=i+1
sleep(0.1)
sys.stdout.flush()
django urls.py
lập bản đồ:
urlpatterns = patterns('',
(r'^startjob/$', 'mysite.myapp.views.startjob'),
(r'^showjob/$', 'mysite.myapp.views.showjob'),
(r'^rmjob/$', 'mysite.myapp.views.rmjob'),
)
xem django:
from tempfile import mkstemp
from os import fdopen,unlink,kill
from subprocess import Popen
import signal
def startjob(request):
"""Start a new long running process unless already started."""
if not request.session.has_key('job'):
# create a temporary file to save the resuls
outfd,outname=mkstemp()
request.session['jobfile']=outname
outfile=fdopen(outfd,'a+')
proc=Popen("python myjob.py",shell=True,stdout=outfile)
# remember pid to terminate the job later
request.session['job']=proc.pid
return HttpResponse('A <a href="/showjob/">new job</a> has started.')
def showjob(request):
"""Show the last result of the running job."""
if not request.session.has_key('job'):
return HttpResponse('Not running a job.'+\
'<a href="/startjob/">Start a new one?</a>')
else:
filename=request.session['jobfile']
results=open(filename)
lines=results.readlines()
try:
return HttpResponse(lines[-1]+\
'<p><a href="/rmjob/">Terminate?</a>')
except:
return HttpResponse('No results yet.'+\
'<p><a href="/rmjob/">Terminate?</a>')
return response
def rmjob(request):
"""Terminate the runining job."""
if request.session.has_key('job'):
job=request.session['job']
filename=request.session['jobfile']
try:
kill(job,signal.SIGKILL) # unix only
unlink(filename)
except OSError, e:
pass # probably the job has finished already
del request.session['job']
del request.session['jobfile']
return HttpResponseRedirect('/startjob/') # start a new one
Vui lòng cung cấp mã bạn đang làm để sinh ra quá trình xử lý nền. Có rất nhiều cách để làm điều này, bạn đang sử dụng cái nào? –