2012-11-08 29 views
5

Tôi đang tạo một ứng dụng web bằng cách sử dụng Python + Tornado mà về cơ bản phục vụ tệp cho người dùng. Tôi không có cơ sở dữ liệu.Tornado async gọi đến một hàm

Các tệp được trực tiếp đón và phân phát nếu chúng có sẵn hoặc được tạo khi đang di chuyển nếu không.

Tôi muốn khách hàng được phục vụ theo cách không đồng bộ, vì một số tệp có thể đã có sẵn, trong khi các tệp khác cần được tạo (vì vậy chúng cần đợi và tôi không muốn chúng chặn người dùng khác).

Tôi có một lớp học quản lý việc chọn hoặc tạo tệp và tôi chỉ cần gọi nó từ Tornado.

Cách tốt nhất (hiệu quả nhất trên CPU và RAM) để đạt được điều đó là gì? Tôi có nên sử dụng một sợi không? Một tiến trình phụ? Một đơn giản gen.Task like this one?

Ngoài ra, tôi muốn triển khai của mình hoạt động trên Công cụ ứng dụng của Google (Tôi cho rằng chúng không cho phép các quy trình phụ được sinh ra?).

Tôi tương đối mới đối với dịch vụ web không đồng bộ, vì vậy mọi trợ giúp đều được chào đón.

+1

Các gen.Task sẽ hoạt động tốt. Nếu tập tin của bạn nhận được/tạo ra mã không thể chơi độc đáo trong đó sau đó một sợi sẽ làm việc tốt. Bạn cũng có thể sinh ra nhiều quy trình, nhưng tôi không biết các giới hạn trên Google App Engine. – sean

+0

Cảm ơn bạn đã trả lời. Bạn cũng biết làm thế nào nó sẽ làm việc ra nếu tôi đẻ trứng nhiều gen.Task? Tôi có nghĩa là, ** phương pháp dụ ** của tôi có thể khá CPU và tốn thời gian, nếu phương pháp này được gọi nhiều lần từ nhiều người dùng, điều gì sẽ xảy ra?Tất cả các phương thức có chạy không đồng bộ song song hoặc các phương thức tiếp theo sẽ chờ các phương thức trước đó kết thúc trước? (lưu ý rằng tôi có một trường hợp duy nhất trong lớp của mình mà tôi sử dụng trong toàn bộ ứng dụng của mình) – gaborous

+1

Hoàn toàn bị xóa, nó sẽ ổn, nhưng bất kể giải pháp của bạn, nó sẽ trở thành vấn đề với rất nhiều luồng bất kể. Nếu đây là một lo lắng, hãy thử xem xét tách thành các quá trình riêng biệt hoặc chạy nhiều trường hợp phía sau cân bằng tải. – sean

Trả lời

10

Tôi đã tìm thấy câu trả lời cho câu hỏi của mình: Ví dụ genTask thực sự là cách tốt nhất để thực hiện cuộc gọi không đồng bộ và do thực tế là ví dụ sử dụng Python coroutine, mà tôi đã không làm t hiểu ngay từ cái nhìn đầu tiên bởi vì tôi nghĩ rằng sản lượng chỉ được sử dụng để trả về một giá trị cho máy phát điện.

dụ bê tông:

  • năng suất, mà trên thực tế spawns một coroutine (hoặc giả chủ đề, đó là:

    class MyHandler(tornado.web.RequestHandler): 
    
        @asynchronous 
        @gen.engine 
        def get(self): 
         response = yield gen.Task(self.dosomething, 'argument') 
    

    gì là quan trọng ở đây là sự kết hợp của hai điều là rất hiệu quả và được thực hiện để có tính đồng thời cao). http://www.python.org/dev/peps/pep-0342/

  • gen.Task() là chức năng không chặn (không đồng bộ), vì nếu bạn sinh ra một coroutine trên chức năng chặn, nó sẽ không đồng bộ. gen.Task() được cung cấp bởi Tornado, đặc biệt để làm việc với cú pháp coroutine của Python. Infos thêm: http://www.tornadoweb.org/documentation/gen.html

Vì vậy, một ví dụ kinh điển của một cuộc gọi async bằng Python sử dụng coroutines:

response = yield non_blocking_func(**kwargs) 
+1

Ngoài ra, đây là một bài đăng khác được nêu chi tiết về cả triển khai thực hiện lại coroutine và gọi lại cũ: http://stackoverflow.com/questions/8812715/using-a-simple-python-generator-as-a-co-routine-in -a-tornado-async-handler? rq = 1 – gaborous

1

Bây giờ Documentation có giải pháp.

đơn giản ví dụ:

import os.path 
import tornado.web 
from tornado import gen 

class MyHandler(tornado.web.RequestHandler): 

    @gen.coroutine 
    def get(self, filename): 
     result = yield self.some_usefull_process(filename) 
     self.write(result) 

    @gen.coroutine 
    def some_usefull_process(self, filename): 
     if not os.path.exists(filename): 
      status = yield self.generate_file(filename) 
      result = 'File created' 
     else: 
      result = 'File exists' 

     raise gen.Return(result) 

    @gen.coroutine 
    def generate_file(self, filename): 
     fd = open(filename, 'w') 
     fd.write('created') 
     fd.close() 
Các vấn đề liên quan