【问题标题】:Optimising RSS parsing on App Engine to avoid high CPU warnings优化 App Engine 上的 RSS 解析以避免高 CPU 警告
【发布时间】:2010-04-01 20:48:16
【问题描述】:

我将一些 RSS 提要提取到 App Engine 中的数据存储区,以便为 iPhone 应用程序提供服务。我使用 cron 来安排每 x 分钟更新一次 RSS。每个任务只解析一个 RSS 提要(有 15-20 项)。我经常在 App Engine 仪表板中收到有关 CPU 使用率过高的警告,因此我正在寻找优化代码的方法。

目前,我使用 minidom(因为它已经在 App Engine 上),但我怀疑它不是很有效!

代码如下:

 dom = minidom.parseString(urlfetch.fetch(url).content)
    if dom:
        items = []
        for node in dom.getElementsByTagName('item'):
            item = RssItem(
                key_name = self.getText(node.getElementsByTagName('guid')[0].childNodes),
                title = self.getText(node.getElementsByTagName('title')[0].childNodes),
                description = self.getText(node.getElementsByTagName('description')[0].childNodes),
                modified = datetime.now(),
                link = self.getText(node.getElementsByTagName('link')[0].childNodes),
                categories = [self.getText(category.childNodes) for category in node.getElementsByTagName('category')]
            );
            items.append(item);
        db.put(items);

def getText(self, nodelist):
    rc = ''
    for node in nodelist:
        if node.nodeType == node.TEXT_NODE:
            rc = rc + node.data
    return rc

没有发生太多事情,但脚本通常需要 2-6 秒的 CPU 时间,这对于循环 20 多个项目和读取一些属性来说似乎有点过分。

我可以做些什么来加快速度?上面的代码有什么特别糟糕的地方,还是我应该改用另一种解析方式?有没有更好的库(适用于 App Engine),或者我自己会更好地解析 RSS?

【问题讨论】:

  • 嗨,丹尼,我更新了我的评论,加入了 brett slatkin 的视频,他还不得不解决解析速度变慢的问题,并编写了自己的闪电般快速的实现。

标签: python google-app-engine


【解决方案1】:

通过例如 superfeedr 外包 feed 解析

您也可以查看superfeedr.com。他们有合理的免费配额/付费计划。他们将为您/等进行投票(在 15 分钟内获得更新)。如果提要也支持pubsubhubbub,那么您将实时收到提要!如果您还不知道pubsubhubbub 是什么,该视频将向您解释。

Brett Slatkin 编写的改进的 feed 解析器

我还建议您观看来自 Brett Slatkin 的精彩 video 解释 pubsubhubbub。我还记得在演示文稿的某个地方,他说他不使用Universal Feedparser,因为它对他的问题有很大的帮助。他编写了自己的 SAX(14:10 在视频演示中他谈到了一点)解析器,速度快如闪电。我想你应该查看 pubsubhubbub code 了解他是如何做到这一点的。

【讨论】:

  • +1。让其他人为您完成大部分工作,然后您只需要解析新条目。它也不必是超级馈送器:任何支持轮询的喧嚣集线器都可以。
  • 这比我希望的要多,因为我认为 6 秒来解析 20 个项目是很糟糕的,我希望通过相对较小的更改来修复它。也就是说,我需要更新我的提要,因为 1% 的项目是新的,所以我做了很多重复的工作,所以这可能是一个值得的改变。我会让应用程序的其余部分正常工作,并在完成所有其他工作后考虑这一点:-)
  • @Nick Johnson 我认为 superfeedr 是唯一支持投票的公共 pubsubhubbub。你也认识其他人吗?
  • 我不知道任何 - 这并不是说不存在。你甚至可以在 apppot 上运行你自己的。我只是想指出 superfeedr 并不是独一无二的。 :)
【解决方案2】:

如果您的网站访问量较少,您的应用可能会出现启动时间。如果一个应用程序闲置了几分钟,应用程序引擎将关闭您的应用程序以节省资源。当下一个请求进入应用程序时,必须先启动它才能处理请求,这一切都会添加到您的 CPU 配额中。如果您搜索 appengine 新闻组,您会发现它充满了对此的抱怨。

我为我的网站www.newsfacet.com 使用 superfeedr,我注意到当 superfeedr 通知我时,我可以在几百毫秒内处理几篇 rss 文章。如果距离上次输入已经有一段时间了,那么这次可能会跳到 10 或 11 秒,因为它会产生加速成本。

【讨论】:

  • 我同意在这种情况下,启动时间可能是您的问题。
  • 这完全有可能 - 我会调查 :-)
  • 实现 servlet init 方法并从那里记录一条消息,每次启动时都会告诉您。
【解决方案3】:

关于使用 PubSubHubbub 让其他人为您完成工作,您可能会发现我的 blog post on using hubbub on App Engine 很有用。

【讨论】:

    【解决方案4】:

    我会尝试ElementTreeUniversal Feed Parser 看看它们是否更好。 ElementTree 在 Python 2.5 的标准库中,因此可在 App Engine 上使用。

    【讨论】:

    • 我会检查这些。我以前使用过 minidom,发现它非常占用 CPU,所以我确信肯定有更高效的东西。
    【解决方案5】:

    您可能应该运行分析器来查明代码在哪里旋转。它可能正在等待连接,因为某些 RSS 提要真的很慢。

    此外,一些 RDF/RSS/ATOM 库内置了一个调控器,以防止在从同一站点检索多个提要时将 cr*p 击败主机。我已经写了几个聚合器,考虑到服务器很重要。

    Universal Feed Parser 功能齐全,至少从我通过查看文档看到的情况来看是这样。我没有使用它,因为我用 Ruby 编写了聚合器并且有不同的需求,但我知道它并会考虑将它用于基于 Python 的解决方案。

    【讨论】:

    • “它可能正在等待连接”。不过,这不应该算作 CPU 时间。
    • 正如 Thilo 所说,在等待服务器响应时不应计入 CPU 时间。您知道任何可以提供详细信息的个人资料吗?我已经为 .NET 使用过 Red-Gate ANT(这很棒),但我还没有看到过类似的 Python(我使用过 Guido 的 AppStats,但它只是 API 调用)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    • 1970-01-01
    • 2013-05-25
    • 2012-04-02
    • 2015-02-04
    • 1970-01-01
    相关资源
    最近更新 更多