Làm cách nào để chạy các tác vụ nền trên appengine?Nhiệm vụ nền trên appengine
Trả lời
GAE là công cụ rất hữu ích để xây dựng các ứng dụng web có thể mở rộng. Một số hạn chế được chỉ ra bởi nhiều người không hỗ trợ cho các tác vụ nền, thiếu các nhiệm vụ định kỳ và giới hạn nghiêm ngặt về thời gian mỗi yêu cầu HTTP mất đi, nếu yêu cầu vượt quá giới hạn thời gian đó. .
Cách chạy tác vụ nền?
Trong GAE, mã được thực thi chỉ khi có yêu cầu HTTP. Có một giới hạn thời gian nghiêm ngặt (tôi nghĩ 10 giây) về việc mã có thể mất bao lâu. Vì vậy, nếu không có yêu cầu thì mã sẽ không được thực thi. Một trong những công việc được đề xuất xung quanh là sử dụng một hộp bên ngoài để gửi yêu cầu liên tục, do đó, loại tạo ra một nhiệm vụ nền. Nhưng đối với điều này chúng ta cần một hộp bên ngoài và bây giờ chúng ta phụ thuộc vào một yếu tố nữa. Cách khác là gửi 302 phản hồi chuyển hướng để khách hàng gửi lại yêu cầu, điều này cũng làm cho chúng ta phụ thuộc vào yếu tố bên ngoài là khách hàng. Điều gì xảy ra nếu hộp bên ngoài đó chính là GAE? Tất cả những người đã sử dụng ngôn ngữ chức năng mà không hỗ trợ xây dựng vòng lặp trong ngôn ngữ nhận thức được sự thay thế tức là thay thế cho vòng lặp. Vì vậy, những gì nếu chúng ta hoàn thành một phần của tính toán và làm một HTTP GET trên cùng một url với thời gian rất ngắn ra nói 1 giây? Điều này tạo ra một vòng lặp (đệ quy) trên mã php chạy trên apache.
<?php $i = 0; if(isset($_REQUEST["i"])){ $i= $_REQUEST["i"]; sleep(1); } $ch = curl_init("http://localhost".$_SERVER["PHP_SELF"]."?i=".($i+1)); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_TIMEOUT, 1); curl_exec($ch); print "hello world\n"; ?>
Một số cách thức này không hoạt động trên GAE. Vì vậy, nếu chúng ta làm HTTP GET trên một số url khác nói url2 mà hiện HTTP GET trên url đầu tiên? Điều này dường như hoạt động trong GAE. Mã cho cái này trông như thế này
class FirstUrl(webapp.RequestHandler): def get(self): self.response.out.write("ok") time.sleep(2) urlfetch.fetch("http://"+self.request.headers["HOST"]+'/url2') class SecondUrl(webapp.RequestHandler): def get(self): self.response.out.write("ok") time.sleep(2) urlfetch.fetch("http://"+self.request.headers["HOST"]+'/url1') application = webapp.WSGIApplication([('/url1', FirstUrl), ('/url2', SecondUrl)]) def main(): run_wsgi_app(application) if __name__ == "__main__": main()
Vì chúng tôi đã tìm ra cách để chạy tác vụ nền, cho phép xây dựng trừu tượng cho công việc định kỳ (hẹn giờ) và cấu trúc vòng lặp trải rộng trên nhiều yêu cầu HTTP (foreach).
Hẹn giờ
Giờ xây dựng ngay lập tức. Ý tưởng cơ bản là có danh sách các bộ đếm thời gian và khoảng thời gian mà mỗi cái sẽ được gọi. Khi chúng tôi đạt đến khoảng thời gian đó, hãy gọi hàm gọi lại. Chúng tôi sẽ sử dụng memcache để duy trì danh sách hẹn giờ. Để tìm hiểu khi nào gọi lại gọi lại, chúng tôi sẽ lưu trữ một khóa trong memcache với khoảng thời gian hết hạn. Chúng tôi định kỳ (nói 5 giây) kiểm tra xem khóa đó có hiện diện không, nếu không có thì gọi lại cuộc gọi và đặt lại khóa đó với khoảng thời gian.
def timer(func, interval): timerlist = memcache.get('timer') if(None == timerlist): timerlist = [] timerlist.append({'func':func, 'interval':interval}) memcache.set('timer-'+func, '1', interval) memcache.set('timer', timerlist) def checktimers(): timerlist = memcache.get('timer') if(None == timerlist): return False for current in timerlist: if(None == memcache.get('timer-'+current['func'])): #reset interval memcache.set('timer-'+current['func'], '1', current['interval']) #invoke callback function try: eval(current['func']+'()') except: pass return True return False
Foreach
này là cần thiết khi chúng ta muốn làm tính toán lấy dài nói làm một số hoạt động trên 1000 hàng cơ sở dữ liệu hoặc lấy 1000 url vv Ý tưởng cơ bản là để duy trì danh sách các callbacks và lập luận trong memcache và mỗi lần gọi gọi lại với đối số.
def foreach(func, args): looplist = memcache.get('foreach') if(None == looplist): looplist = [] looplist.append({'func':func, 'args':args}) memcache.set('foreach', looplist) def checkloops(): looplist = memcache.get('foreach') if(None == looplist): return False if((len(looplist) > 0) and (len(looplist[0]['args']) > 0)): arg = looplist[0]['args'].pop(0) func = looplist[0]['func'] if(len(looplist[0]['args']) == 0): looplist.pop(0) if((len(looplist) > 0) and (len(looplist[0]['args']) > 0)): memcache.set('foreach', looplist) else: memcache.delete('foreach') try: eval(func+'('+repr(arg)+')') except: pass return True else: return False # instead of # foreach index in range(0, 1000): # someoperaton(index) # we will say # foreach('someoperaton', range(0, 1000))
Bây giờ, hãy tạo một chương trình tìm nạp danh sách url mỗi một giờ về phía trước. Đây là mã.
def getone(url): try: result = urlfetch.fetch(url) if(result.status_code == 200): memcache.set(url, '1', 60*60) #process result.content except : pass def getallurl(): #list of urls to be fetched urllist = ['http://www.google.com/', 'http://www.cnn.com/', 'http://www.yahoo.com', 'http://news.google.com'] fetchlist = [] for url in urllist: if (memcache.get(url) is None): fetchlist.append(url) #this is equivalent to #for url in fetchlist: getone(url) if(len(fetchlist) > 0): foreach('getone', fetchlist) #register the timer callback timer('getallurl', 3*60)
mã hoàn chỉnh là ở đây http://groups.google.com/group/httpmr-discuss/t/1648611a54c01aa Tôi đã được chạy mã này vào appengine cho vài ngày mà không có nhiều vấn đề.
Cảnh báo: Chúng tôi sử dụng nhiều urlfetch. Giới hạn không có urlfetch mỗi ngày là 160000. Vì vậy, hãy cẩn thận để không đạt đến giới hạn đó.
tuyệt vời! Tôi thích nó – fuentesjr
Tôi không thấy nó có thể hoạt động như thế nào. Bạn sẽ không vượt quá 10 giây hạn ngạch trên lần tìm nạp đệ quy thứ 6? – Constantin
Đúng nếu tôi sai, không có chính sách AppEngine về liên lạc giữa các ứng dụng được lưu trữ không? – zotherstupidguy
Phiên bản thời gian chạy sắp tới sẽ có một số loại động cơ thực thi định kỳ a'la cron. Xem this message trên nhóm AppEngine.
Vì vậy, tất cả các phần SDK dường như hoạt động, nhưng thử nghiệm của tôi cho biết điều này hiện không chạy trên máy chủ sản xuất-- Tôi thiết lập cron "cứ 1 phút" khi nhật ký chạy và chưa được gọi là chưa
Khó nói khi điều này sẽ có sẵn, mặc dù ...
Bạn có thể sử dụng Task Queue Python API.
Sử dụng Queue công tác - http://code.google.com/appengine/docs/java/taskqueue/overview.html
-1; đây thực chất là cùng một câu trả lời được đăng và được chấp nhận 2 năm trước, với một liên kết tới các tài liệu Java thay vì các tài liệu Python, khi OP sử dụng Python. Nghiêm túc? – geoffspear
Nếu bạn muốn chạy nền nhiệm vụ tuần hoàn, xem this question (AppEngine cron)
Nếu nhiệm vụ của bạn là không định kỳ, xem Task Queue Python API hoặc Task Queue Java API
Bạn có thể tìm thêm về cron jobs trong Python App Engine here.
Có một cơ sở cron được tích hợp sẵn trong công cụ ứng dụng.
Vui lòng tham khảo: https://developers.google.com/appengine/docs/python/config/cron?hl=en
Sử dụng Deferred Python Library là cách dễ nhất để làm nhiệm vụ cơ bản về AppEngine sử dụng Python được xây dựng trên đầu trang của hàng tác vụ API.
from google.appengine.ext import deferred
def do_something_expensive(a, b, c=None):
logging.info("Doing something expensive!")
# Do your work here
# Somewhere else
deferred.defer(do_something_expensive, "Hello, world!", 42, c=True)
Có những ưu điểm và nhược điểm khi sử dụng thư viện hoãn lại, xem phần "Khi nào sử dụng ext.deferred" trong bài viết của Nick Johnson: https://cloud.google.com/appengine/articles/deferred?hl=vi –
- 1. Rails Nhiệm vụ nền trên không
- 2. Hàng đợi nhiệm vụ thử nghiệm đơn vị trong AppEngine
- 3. Nhiệm vụ nền lặp lại đáng tin cậy trên android
- 4. Nhiệm vụ nền cần tây Heroku
- 5. MiniProfiler, EntityFramework mã đầu tiên và nền nhiệm vụ nullreference
- 6. Khung dịch vụ RESTFul cho AppEngine
- 7. Trọng tải nhiệm vụ của appengine có thể lớn đến mức nào?
- 8. Dịch vụ dữ liệu dựa trên nhiệm vụ trong Silverlight
- 9. Làm thế nào để bắt đầu nhiệm vụ nền chạy dài trong dịch vụ android
- 10. Vòng đời nhiệm vụ
- 11. Hạn chót nhiệm vụ của Máy ứng dụng của Google
- 12. Servlet 3 Nhiệm vụ không đồng bộ trên Tomcat 7
- 13. hoàn thành nhiệm vụ
- 14. GenerateOfficeAddInManifest lỗi nhiệm vụ
- 15. cào biến nhiệm vụ
- 16. nhiệm vụ android giết
- 17. django trên Google Appengine
- 18. Kiểm tra Nhiệm vụ Rake
- 19. Mô phỏng tác vụ nền trên AppHarbor
- 20. nhiệm vụ định kỳ đường ray
- 21. ContinueWith một hủy nhiệm vụ
- 22. Status 405 từ hàng đợi nhiệm vụ
- 23. Nhiệm vụ cào đa luồng
- 24. đồ thị quan hệ nhiệm vụ dựa trên JIRA
- 25. Đặt lại đếm ngược trên nhiệm vụ cần tây
- 26. Azure - xếp hàng các nhiệm vụ dựa trên thời gian
- 27. sbt Đường dẫn nhiệm vụ
- 28. Làm thế nào để Async.AwaitTask trên nhiệm vụ đồng bằng (không phải nhiệm vụ <T>)?
- 29. Django Celery nhận nhiệm vụ
- 30. Cách thích hợp để bắt đầu nhiệm vụ theo lịch trình trên nền tảng Java EE 5 (JBoss) là gì?
Bạn có lẽ nên xóa thẻ php, vì php không hoạt động trên GAE. –