Python:用于url轮询和发布的体系结构

时间:2009-11-15 22:58:57

标签: python architecture concurrency

我有一个简单的问题。我必须获取一个网址(大约每分钟一次),检查是否有新内容,如果有,请将其发布到另一个网址。

我每分钟都有一个带有cronjob的工作系统,基本上是:

for link in models.Link.objects.filter(enabled=True).select_related():
    # do it in two phases in case there is cross pollination

    # get posts
    twitter_posts, meme_posts = [], []
    if link.direction == "t2m" or link.direction == "both":
        twitter_posts = utils.get_twitter_posts(link)

    if link.direction == "m2t" or link.direction == "both":
        meme_posts = utils.get_meme_posts(link)

    # process them
    if len(twitter_posts) > 0:
        post_count += views.twitter_link(link, twitter_posts)

    if len(meme_posts) > 0:
        post_count += views.meme_link(link, meme_posts)

    count += 1

msg = "%s links crawled and %s posts updated" % (count, post_count)

这对我现在拥有的150个用户来说非常有用,但它的同步性让我感到害怕。我有内置的url超时,但在某些时候我的cronjob将采取> 1分钟,我将留下一百万人在另外一起覆盖。

那么,我应该如何重写呢?

一些问题:

  • 我不想太难看它们阻止我。所以我希望任何时候最多可以与任何API建立5个开放连接。
  • 用户继续在系统中注册,因此我需要一些方法来添加它们
  • 我希望能够尽可能地扩展
  • 我想尽可能多地重用现有代码

所以,我有过一些想法:

  • 为每个link
  • 生成一个帖子
  • 使用python-twisted - 保持一个正在运行的进程,cronjob确保正在运行。
  • 使用stackless - 对此并不太了解。
  • 问StackOverflow:)

你会怎么做?

1 个答案:

答案 0 :(得分:2)

最简单:使用sched(在其自己的线程上)长时间运行的进程来处理调度 - 通过将请求发布到Queue;有一个固定大小的线程池(你可以找到一个预先制作的线程池here,但很容易调整它或自己动摇)从队列中获取请求(并通过一个单独的队列返回结果)。如果需要,可以通过一些专用线程来处理注册和其他系统功能。

线程并不是那么糟糕,只要(a)你永远不必担心它们之间的同步(只是让它们通过本质上线程安全的队列实例进行通信,永远不会共享对任何线程的访问权限不严格只读的结构或子系统,以及(b)你从来没有太多(使用一些专用线程用于专门的功能,包括调度,以及用于一般工作的小线程池 - never 每个请求或类似的东西产生一个线程,它会爆炸)。

Twisted可以更具可扩展性(以较低的硬件成本),但是如果您在threading(和队列)上铰接架构,则可以通过内置方式来扩展系统(通过购买更多硬件)来使用非常相似的multiprocessing模块而不是......几乎是一个简单的替代品,可能会扩大数量级! - )