Как выполнять фоновые задачи на appengine?Фоновые задачи на appengine
ответ
GAE - очень полезный инструмент для создания масштабируемых веб-приложений. Немногие из ограничений, на которые указывают многие, не поддерживают фоновые задачи, отсутствие периодических заданий и строгий лимит времени, в течение которого каждый HTTP-запрос берется, если запрос превышает это ограничение времени, операция прекращается, что делает невозможным выполнение длительных задач ,
Как выполнить фоновое задание?
В GAE код выполняется только при наличии HTTP-запроса. Существует строгий лимит времени (я думаю, 10 секунд) о том, сколько времени может пройти код. Поэтому, если запросов нет, код не выполняется. Одной из предложенных работ было использование внешнего окна для отправки запросов непрерывно, поэтому создание фоновой задачи. Но для этого нам нужен внешний ящик, и теперь мы зависим от еще одного элемента. Другая альтернатива отправляла 302 ответ перенаправления, чтобы клиент повторно отправил запрос, это также заставляет нас зависить от внешнего элемента, который является клиентом. Что, если этот внешний ящик сам GAE? Каждый, кто использовал функциональный язык, который не поддерживает конструкцию цикла в языке, знает об альтернативе, т. Е. Рекурсия является заменой циклу. Итак, что, если мы закончим часть вычисления и сделаем HTTP GET на одном и том же URL с очень коротким временем, скажем, 1 секунду? Это создает цикл (рекурсия) в php-коде, запущенном на 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"; ?>
Некоторые, как это не работает на GAE. Итак, что, если мы делаем HTTP GET на каком-то другом url, говорим url2, который делает HTTP GET на первом URL? Это похоже на работу в GAE. Код для этого выглядит так.
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()
Поскольку мы обнаружили способ запустить фоновую задачу, позволяет строить абстракции для периодической задачи (таймер) и создания циклов, которая охватывает во многих запросах HTTP (Foreach).
Таймер
Теперь таймер построения прямолинейный. Основная идея состоит в том, чтобы иметь список таймеров и интервал, по которому каждый должен быть вызван. Как только мы достигнем этого интервала, вызовите функцию обратного вызова. Мы будем использовать memcache для сохранения списка таймеров. Чтобы узнать, когда вызывать обратный вызов, мы будем хранить ключ в memcache с интервалом как время истечения. Мы периодически (скажем, 5 секунд) проверяем, присутствует ли этот ключ, если нет, то вызывайте обратный вызов и снова устанавливайте эту клавишу с интервалом.
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
Это необходимо, когда мы хотим сделать длинные принимая вычисления говорят, делают какую-то операцию на 1000 строк базы данных или получать 1000 URLs и т.д. Основная идея заключается в том, чтобы поддерживать список обратных вызовов и аргументы в кэше и каждый раз вызывайте обратный вызов с аргументом.
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))
Теперь создаем программу, которая выбирает список URL-адресов каждый час прямо. Вот код.
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)
полный код здесь http://groups.google.com/group/httpmr-discuss/t/1648611a54c01aa я был запущен этот код на AppEngine за несколько дней без особых проблем.
Предупреждение: Мы активно используем urlfetch. Предел по отсутствию urlfetch в день составляет 160000. Поэтому будьте осторожны, чтобы не достичь этого предела.
потрясающий! Мне нравится – fuentesjr 2008-10-01 04:47:50
Я не вижу, как это может работать. Разве вы не превысите 10-секундную квоту на 6-й рекурсивной выборке? – Constantin 2008-10-03 20:43:44
Исправьте меня, если я ошибаюсь, нет ли политики AppEngine относительно взаимодействия между размещенными приложениями? – zotherstupidguy 2009-05-04 21:12:01
В верхней и следующей версиях среды выполнения будет установлен механизм периодического выполнения a'la cron. См. this message в группе AppEngine.
Итак, все части SDK работают, но мое тестирование указывает на то, что это еще не работает на производственных серверах. Я установил «каждые 1 минуту» cron, который регистрируется при запуске, и это не был вызван еще
Трудно сказать, когда это будет доступно, хотя ...
Вы можете использовать Task Queue Python API.
Используйте очереди задач - http://code.google.com/appengine/docs/java/taskqueue/overview.html
Если вы хотите запускать фоновые периодические задачи см this question (AppEngine хрон)
Если ваши задачи не являются периодическими, см Task Queue Python API или Task Queue Java API
Вы можете найти больше о работе cron в Python App Engine here.
В приложение включено встроенное средство cron.
Пожалуйста, обратитесь к: https://developers.google.com/appengine/docs/python/config/cron?hl=en
Использование Deferred Python Library это самый простой способ сделать фоновую задачу на Appengine с помощью Python, который построен на вершине TaskQueue 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)
- 1. Фоновые задачи
- 2. Фоновые задачи таймеры на iOS
- 3. Фоновые задачи запускаются вечно?
- 4. Django фоновые задачи
- 5. Фоновые задачи в WinRT
- 6. Граали и фоновые задачи
- 7. Фоновые задачи в Azure
- 8. Фоновые задачи весной (AMQP)
- 9. Фоновые задачи не работают
- 10. Фоновые задачи и активность
- 11. Node.js фоновые задачи
- 12. Фоновые задачи, если пользователи находятся на сайте
- 13. Параллельные фоновые задачи на одном рабочем диноте
- 14. Nokia Asha SDK Фоновые задачи
- 15. Фоновые задачи в ASP.NET/Debug
- 16. AFNetworking 2 и фоновые задачи
- 17. Windows Azure - фоновые/запланированные задачи?
- 18. Долгосрочные процессы ввода-вывода в AppEngine: задачи или потоки?
- 19. AppEngine «Размер задачи слишком большой»
- 20. Appengine Push Queue Состояние задачи
- 21. AppEngine: gaierror при запуске задачи
- 22. Фоновые задачи и очередь с django
- 23. Проект Java Maven создает фоновые задачи
- 24. Windows 8 показывает все фоновые задачи
- 25. Как запустить фоновые задачи в React Native?
- 26. Выполняя многолетние фоновые задачи в phonegap
- 27. Фоновые задачи в Axis2 - стек Tomcat
- 28. Как запускать фоновые задачи в Android
- 29. sonarqube: почему фоновые задачи видны только администраторам?
- 30. Два одновременные фоновые задачи с использованием NSOperationQueue
Возможно, вы должны удалить тег php, поскольку php не работает с GAE. – 2008-09-30 10:04:30