GAE的任务队列介绍

标签:Google App Engine

GAE Python SDK 1.2.3新增了对任务队列的支持,文档可以看《The Task Queue Python API》

目前这个API还属于实验性质,以后的版本可能会改动接口和行为,所以仅供尝鲜。但连包名都放在labs里面(google.appengine.api.labs.taskqueue),说明这个API是“肯定”会改的,而不是“可能”。如果API确定下来了,最终会被移到google.appengine.api.taskqueue。
此外,这个API也在配额内(目前还未放入),并可能需要billing。

不过也不用我多说了,任务队列突破了30秒的限制(变成了30×N秒),也不像计划任务那样无法在程序中动态设置执行时间,无疑让大型处理成为了可能。


首先说下任务队列的需求。
它必须是由用户请求(包括计划任务请求)来初始化,这个用户请求必须在30秒内结束,但任务队列可在用户请求结束后继续工作,直至完成。
因此如果用户进行了一次操作,但这个操作可能需要超过30秒的时间,而用户并不需要立即得知操作是否成功,则可以用这种方式来处理。(举例来说,一个blog需要在访问者浏览博文时将该博文的浏览数加1,然而该访问者并不关心你是否更新了浏览数,却必须等待数据库更新完才能浏览你的博文;而现在你可以让任务队列去更新数据库,而让浏览者无需等待。)
如果需要更友好的方式,可以提示用户正在处理,然后用AJAX方式查询是否已经完成任务,并提示用户目前的进度或完成情况。
如果你没有这种需求的话,那就不必浪费时间读下文了~


接着来介绍如何使用。

添加任务是用taskqueue.add()函数,此外也可以创建一个Task对象,再调用其add()方法。
出于某些原因,任务不是一个callable对象,而是一个RequestHandler和数据的组合。添加任务时,只需传入用于处理任务的URL和参数(即数据)即可(当然还能指定是用GET还是POST等方法),后台便会异步地访问这个URL了。
从某种意义上来说,这可以算是多线程(只不过不方便同步,或许可用memcache),不过由于是用RequestHandler处理,所以仍然必须在30秒内处理完,但你可以分成多个片段,进行递归处理。甚至可以捕捉到超时异常时,才创建另一个任务继续处理。

而单个任务是没多大用处的,所以还必须了解任务队列这个概念。
一个任务队列里可以放置多个任务,这些任务一般是按照FIFO的方式依次执行的,但GAE可能会根据性能原因而调整其执行顺序。
不同的队列是用队列名来区分的,一个队列名一旦使用,其他队列就不能再使用这个队列名(除非该队列已成功执行7天以上)。
此外,你还可以指定队列的执行频率。例如你可能会将发邮件放在队列中执行,而免费账号每分钟最多只能发送8封邮件,所以你可以设置你的队列每分钟执行一个任务,而这个任务最多发送8封邮件,以避免超出配额。
但这些配置是在queue.yaml文件里设置的,如果不配置的话,队列名将使用default,参数也是缺省的(因此就无法指定频率)。此外,如果把频率设为0,那么这个队列就不会执行了。
任务队列的配置还有个作用:设置缺省的URL。之前说到添加任务需要指定一个处理它的URL,但如果设置了队列的缺省URL,那就可以不指定它了。需要注意的是,如果没有为该URL指定handler,那么这个任务将造成一个404错误;由于任务未执行成功,任务队列将不断执行该任务直至成功,便造成死循环了。

另外一个注意点是一个app的所有版本共用这些任务队列。
你在哪个版本dequeue了一个队列,那么这个队列就会在这个版本执行,不会影响其他版本。但如果你是在default版本运行的,然后又切换了版本,那么队列会在新的default版本运行,这点需要注意。

由于使用非常简单,很类似urlfetch,因此代码我就不列出了,而来看看queue.yaml的配置。
引用一下文档中的配置:
queue:
- name: default
  rate: 1/s
- name: mail-queue
  rate: 2000/d
  bucket_size: 10
- name: background-processing
  rate: 5/s
可以看到配置有3个属性:
name:队列名。你可以在后台的Task Queues项中看到各个队列的情况。
rate:执行频率。s、m、h和d分别表示秒、分、时和天,并用/表示“每”。如果数值为0,则这个任务被暂停。
bucket_size:一个队列中并行执行的任务数目。它受到最大处理速度的限制,缺省值为5。

9条评论 你不来一发么↓ 顺序排列 倒序排列

    向下滚动可载入更多评论,或者点这里禁止自动加载

    想说点什么呢?