2009-05-12 22 views
5

Tôi đang làm việc trên ứng dụng Django cho phép người dùng tải tệp lên. Tôi cần thực hiện một số xử lý phía máy chủ trên các tệp này trước khi gửi chúng đến Amazon S3. Sau khi đọc các câu trả lời cho this questionthis blog post Tôi quyết định cách tốt nhất để xử lý điều này là để trình xử lý xem của tôi gọi phương thức trên đối tượng từ xa Pyro để thực hiện xử lý không đồng bộ và sau đó trả lại ngay Http 200 cho máy khách. Tôi có prototyped này và nó có vẻ hoạt động tốt, tuy nhiên, tôi cũng muốn lưu trữ trạng thái xử lý để client có thể thăm dò ý kiến ​​ứng dụng để xem tập tin đã được xử lý và tải lên S3 chưa.Làm cách nào để lưu trữ trạng thái cho một quy trình chạy dài được gọi từ Django?

Tôi có thể xử lý việc bỏ phiếu dễ dàng đủ, nhưng tôi không chắc vị trí thích hợp để lưu trữ trạng thái quy trình. Nó cần phải được ghi bởi quá trình Pyro và có thể đọc được bằng cách xem bỏ phiếu của tôi.

  • Tôi do dự khi thêm cột vào cơ sở dữ liệu cho dữ liệu thực sự chỉ tồn tại trong 30 đến 60 giây.
  • Tôi đã xem xét sử dụng số low-level cache API của Django và sử dụng id tệp làm khóa, tuy nhiên, tôi không tin rằng đây thực sự là khung bộ nhớ cache được thiết kế và tôi không chắc chắn về những vấn đề không lường trước được tuyến đường.
  • Cuối cùng, tôi đã xem xét lưu trữ trạng thái trong đối tượng Pyro đang xử lý, nhưng sau đó vẫn có vẻ như tôi cần thêm cột cơ sở dữ liệu "processing_complete" boolean để xem có biết truy vấn trạng thái từ Pyro hay không vật.

Tất nhiên, cũng có một số mối quan tâm toàn vẹn dữ liệu với trạng thái tách khỏi cơ sở dữ liệu (điều gì sẽ xảy ra nếu máy chủ bị hỏng và tất cả dữ liệu này nằm trong bộ nhớ?). Tôi muốn biết các nhà phát triển ứng dụng web dày dạn hơn sẽ xử lý loại xử lý trạng thái này như thế nào.

Trả lời

6

Chúng tôi thực hiện việc này bằng cách có bảng "Yêu cầu" trong cơ sở dữ liệu.

Khi tải lên đến, chúng tôi tạo đối tượng Tệp đã tải lên và tạo Yêu cầu.

Chúng tôi bắt đầu bộ xử lý theo lô.

Chúng tôi trả lại trang 200 "chúng tôi đang làm việc trên trang" - nó hiển thị Yêu cầu và trạng thái của chúng.

Bộ xử lý theo lô của chúng tôi sử dụng ORM Django. Khi nó kết thúc, nó cập nhật đối tượng Request. Chúng tôi có thể (nhưng không) gửi thông báo qua email. Chủ yếu, chúng tôi chỉ cập nhật trạng thái để người dùng có thể đăng nhập lại và thấy rằng quá trình xử lý đã hoàn tất.


Ghi chú kiến ​​trúc dòng máy chủ.

Đây là máy chủ WSGI đợi cổng cho yêu cầu xử lý hàng loạt. Yêu cầu là một POST REST với một số ID; bộ xử lý hàng loạt sẽ tìm kiếm trong cơ sở dữ liệu và xử lý nó.

Máy chủ được khởi động tự động bằng giao diện REST của chúng tôi. Nếu nó không chạy, chúng ta sẽ sinh ra nó. Điều này làm cho giao dịch người dùng xuất hiện chậm, nhưng, tốt thôi. Nó không phải là vụ tai nạn.

Ngoài ra, chúng tôi có một crontab đơn giản để kiểm tra xem nó có đang chạy hay không. Tối đa, nó sẽ giảm trong 30 phút giữa "bạn có còn sống không?" kiểm tra.Chúng tôi không có kịch bản khởi động chính thức (chúng tôi chạy dưới Apache với mod_wsgi), nhưng chúng tôi có thể tạo tập lệnh "khởi động lại" chạm vào tệp WSGI và sau đó thực hiện một POST tới URL thực hiện kiểm tra tình trạng (và bắt đầu bộ xử lý hàng loạt).

Khi máy chủ batch bắt đầu, có thể có các yêu cầu chưa được xử lý mà nó chưa bao giờ nhận được POST. Vì vậy, khởi động mặc định là để kéo TẤT CẢ công việc ra khỏi hàng đợi Yêu cầu - giả sử nó có thể đã bỏ sót một cái gì đó.

+0

Sau khi suy nghĩ về điều này qua đêm, tôi đã quyết định rằng bạn hoàn toàn đúng. Nó chỉ không có ý nghĩa để không sử dụng cơ sở dữ liệu. Tôi cũng đã quyết định rằng Pyro là một phù hợp xấu ở đây và rằng tôi chỉ nên làm những gì người bình thường làm và sử dụng một công việc cron với một tập tin khóa. – bouvard

+0

Chúng tôi không sử dụng cron. Chúng tôi có hệ thống lô của chúng tôi như một máy chủ WSGI nhỏ và chúng tôi thực hiện một yêu cầu HTTP với urllib2 để đánh thức nó. Nó nhận được ID yêu cầu từ yêu cầu WSGI; nhận được các chi tiết với Django ORM bình thường. –

+0

Đây là những gì tôi dự định làm với Pyro, nhưng vấn đề tôi thấy trước đó là máy chủ đột ngột ngừng hoạt động có thể để lại tài liệu được xử lý một nửa và sẽ không có thông báo yêu cầu mới để bắt đầu lại quá trình xử lý. Nếu tôi sử dụng một công việc cron tôi biết rằng tôi có thể chỉ cần chọn 10 công việc chưa hoàn thành cũ từ bảng yêu cầu và tôi sẽ đón bất kỳ công việc nào bị cắt trong thời gian cúp điện. – bouvard

1

Vì vậy, đó là hàng đợi công việc mà bạn cần. Đối với trường hợp của bạn, tôi hoàn toàn sẽ đi với DB để tiết kiệm nhà nước, ngay cả khi các tiểu bang đó ngắn ngủi. Có vẻ như điều đó sẽ đáp ứng tất cả các yêu cầu của bạn và không khó thực hiện vì bạn đã có tất cả các bộ phận chuyển động ở đó, có sẵn cho bạn. Hãy đơn giản trừ khi bạn cần điều phức tạp hơn.

Nếu bạn cần thứ gì đó mạnh mẽ hơn hoặc tinh vi hơn, tôi sẽ xem một thứ như Gearman.

5

Tôi biết đây là một câu hỏi cũ nhưng ai đó có thể tìm thấy câu trả lời của tôi hữu ích ngay cả sau tất cả thời gian này, do đó, ở đây đi.

Bạn có thể sử dụng cơ sở dữ liệu làm hàng đợi nhưng có các giải pháp được phát triển chính xác cho mục đích đó.

AMQP chỉ được thực hiện cho điều đó. Cùng với Celery hoặc Carrot và máy chủ môi giới như RabbitMQ hoặc ZeroMQ.

Đó là những gì chúng tôi đang sử dụng trong dự án mới nhất của chúng tôi và nó đang hoạt động rất tốt.

Đối với vấn đề của bạn Celery and RabbitMQ có vẻ như phù hợp nhất. RabbitMQ cung cấp tính bền vững cho các thông điệp của bạn, và Celery cho thấy các khung nhìn dễ dàng cho việc bỏ phiếu để kiểm tra trạng thái của các tiến trình chạy song song.

Bạn cũng có thể quan tâm octopy.

Các vấn đề liên quan