了解 PubSubHubbub

了解如何利用开放源码工具在 Web 上将发布/订阅付诸于实践

PubSubHubbub 是 Web 挂钩的一个开放协议,用于通知某个发布/订阅框架中的新提要的更新。它被定义为一组集成于 Atom 和 RSS 扩展中的 HTTP 服务器到服务器交互。尽管 PubSubHubbub 的名称比较古怪,但用它来设计包含大量信息更新的应用程序却非常简单。本文将了解 PubSubHubbub 的标准、开放源码实现和支持软件。

Uche Ogbuji, 合作伙伴, Zepheira, LLC

Uche Ogbuji 的照片Uche Ogbuji 是 Zepheira 的合作伙伴,这家公司负责监督复杂 Web 目录和其他包含丰富上下文的数据库的创建。Uche Ogbuji 已经花费了很长时间来开创高级 Web 技术(比如 XML、语义 Web 和 Web 服务)、开放源码项目(比如 Akara)以及用于 Web 数据应用程序的开放源码平台。他是一名计算机工程师兼作家,出生在尼日利亚,工作和生活在美国科多拉罗州的博尔德市附近。您可以在他的博客 Copia 上发现有关 Mr.Ogbuji 的更多信息。



2012 年 6 月 01 日

以下几乎是任何文化背景下的每次长途旅行中都会遇到的一个故事情节。坐在后座上的孩子总是不停地问:“我们到了吗?...我们到了吗?...我们到了吗?” 直到恼怒的家长从前座厉声说到:“不要再问了,到了之后我会告诉 您!" 这样的小插曲往往会引来一阵大笑,但是不好笑的是,与那个迫不及待的孩子采用相同做法的情况在 Web 上不知道有多少。

您可能会使用某种提要阅读器来追踪您最喜欢的出版商发布的新内容,不论是新闻站点、博客还是还是像 IBM® developerWorks 这样的日志。如果是这样,您的阅读器习惯上会每隔 15 分钟轮询一次站点并请求提要 URL,或者查看是否存在新的内容。如果您的提要阅读器和站点充分利用了 HTTF 和 Cache-Control(尤其是后者),则会在提要没有更改的情况下将网络交换降至最少。但是,即使利用的资源最少,叠加起来也会造成超时,尤其在您考虑到其他所有人和您一样对同一个站点感兴趣时。

所有这种没必要的流量是一个真正问题,因此,在几年前,Google 的一些工程师决定开发传统发布/订阅模式的一种新形式。发布/订阅就像是车里的家长,他对孩子说 “您告诉我您喜欢的地标,我就会告诉您我们什么时候到那”,所以孩子没必要反复询问 “我们已经到了吗?”。在这种情况下,您可以订阅您感兴趣的提要,该提要的发布者就会注意到您的改变,无需进行轮询。

发布/订阅已经出现有一段时间了,尤其是在关闭的系统中,但是 Web 的开启使其安全有效地实现变得有点棘手。虽然已经有一些早期的研究成果,例如 RSSCloud(参阅 参考资料),但也该是为 Web 使用新一代的发布/订阅的时候了。结果就出现了 PubSubHubbub 这个古怪的名称,通常将其缩写为 "PuSH"。PuSH 可能是 Google 上的极少数原创作品之一,但它也是从一开始就公开开发的一种规范,许多 Google 以外的贡献者都参与了它的研究。更令人高兴的是,该规范已经和一种开放源码参考实现共同开发。曾经也有过其他的一些实现,但是对于某种规范的开发人员而言,能够致力于某个开放源码参考项目来帮助启动社区,这也是一件很好的事。

在本文中,我将介绍 PuSH 并向您展示如何开始使用开放源码参考实现。

PubSubHubbub 简介

在脑海中将 PuSH 组织为发现、订阅和发布三个阶段很有用。本文将概述 PuSH 的大部分主要部件,尽管并非全部(例如,PuSH 有一个经过深思熟虑的取消订阅的机制,这实际上也是 PuSH 自身的一个阶段)。

发现

当订户对某个主题感兴趣时,发现阶段就开始了。PuSH 中的主题基本上就是一个 URL,通常您也可以将它看作一个提要 URL。每一个 IBM developerWorks 专区都有自己的 RSS 提要,而且每一个提要都可以是一个 PuSH 主题,其中的主 URL 与非 PuSH 感知客户端用于轮询的提要 URL 是相同的。

PuSH 的重要改进之一就是允许实际订户不同于管理其 PuSH 订阅的系统,它们甚至可以位于不同的服务器上。这允许用户将部分协议移交给专业的库,甚至移交给 Web 服务。大多数的 PuSH 描述都将订户描述为单一的实体,但我却认为该协议实际上定义了两个单独的实体,我将其中之一称为订户代理,另一个称为订户。在某些情况下,这两者是相继实现的,但是这种情形不是必然的。图 1 是发现过程的图解。

图 1. PuSH 发现过程
图像显示了通过 HTTP GET 或 Atom 的订户代理流量

订户代理代表订户请求提要,并在 PuSH hub 的提交内寻找一个或多个特殊链接。以下就是此种链接的一个例子:

<link rel="hub" href="http://pubsubhubbub.appspot.com"/>

在这种情况下,提要显示 “我在 http://pubsubhubbub.appspot.com 上发布到 PuSH hub”。而这个 PuSH hub 恰好这是 Google 的参考 PuSH hub,运行于 Google App Engine 之上。如果您愿意,您可以使用任何您喜欢的 hub,其中包括您使用 Google 的开放源码实现来运行的一个 hub。

如果没有这样的 PuSH hub 链接,订户代理没有执行进一步的操作,订户必须求助于轮询,或者其他一些机制。如果存在这样的链接,那么下一阶段就是订户联系该 hub,开始订阅阶段。

订阅

图 2 是订阅过程的图解。代理将 HTTP POST 发送至包含回访信息的 hub,该 hub 是应该接收新内容通知的 URL,订户对此处的主题感兴趣。由于还有一个安全机制,所以恶意软件无法通过假装成订户代理来制造破坏,无法让人们订阅他们不需要的提要。

图 2. PuSH 订阅过程
图像显示了 hub 和订户之间通过 HTTP GET、Confirmation 和 HTTP POST 的订阅流

一旦完成了订阅,hub 就会将回访 URL 添加到其订户代理列表中,以便通知发布人是否对内容进行了任何更改。

发布

图 3 是发布过程的图解。当主题更新后,就会使用已更新内容的 URL 将 HTTP POST 发送至其每一个 hub。PuSH 规范将这称为 “新内容通知”。然后每一个 hub 都会发送一个针对主题的新内容的 GET 请求,也称为 “内容提取”。接着该 hub 会在一个称作 “内容分发” 的过程中通过 HTTP POST 将更新的内容发送给每一个订户。

图 3. PuSH 发布过程
图像显示了 PuSH hub 和订户之间通过 HTTP GET、Confirmation 和 HTTP POST 的发布流

PuSH 的能力

所有这些看起来像是一个相当精细的操作,但在交换过程中稍微有点复杂,PUSH 提供了大量分散化操作,因此更具可扩展性和灵活性。图 4 只是说明了在 PUSH 网络中,交互在多个 hub、发布者、订户和订户代理之间是多么的灵活。

图 4. 多个订户、订阅代理、hub 和发布者之间的交互
图像显示了订户、订户代理、hub 和发布者之间的交互

“给我看代码”

既然您对协议有了基本的了解,我将向您展示如何使用 Google 的 PuSH 参考实现,它是开放源码的(Apache 许可证)。我将重点介绍订阅实现,它允许您建立充当订户的系统。

从项目的 Subversion 存储库中检查代码(参阅 参考资料)并快速浏览。“订户” 目录是一个完整的 App Engine 应用程序,它没有包含在我所描述的订阅代理部分,您必须自己补充这方面的知识。您可以从已包含的一些 PHF 代码开始了解 “订阅代理” 目录。

订户不能位于防火墙后面,除非您想额外花费一些精力来配置您的路由器,从而使这一切行得通。您可以使用 Google App Engine SDK(参阅 参考资料)部署您自己的 App Engine 帐户上的订户, 或者您可以使用 SDK 在任何您选择的 Linux 主机上托管代码的测试版本。IBM 确实提供了 App Engine 支持工具(参阅 参考资料 ),以便将应用程序移植到 IBM 中间件,但它们需要一个 Java™ 实现,而 PubSubHubbub 参考实现是用 Python 编写的。我将向您演示使用 SDK 在 Linux® 主机上托管应用程序的情形。在这种情况下,您不会拥有 Google 数据存储后端的所有可扩展性,但不管怎样,这对于单纯的订户而言是没有必要的。清单 1 显示了这个过程。

清单 1. 设置 PubSubHubbub
#Set up the App engine SDK
mkdir -p $HOME/.local/gae
cd $HOME/.local/gae
#Use wget or curl -O
wget http://googleappengine.googlecode.com/files/google_appengine_1.6.2.zip
unzip google_appengine_1.6.2.zip 

#Set up the PubSubHubbub app
svn checkout http://pubsubhubbub.googlecode.com/svn/trunk/ pubsubhubbub-read-only
google_appengine/dev_appserver.py  --address=$ADDR pubsubhubbub-read-only/subscriber/

最后一行代码在端口 8080 上启动了服务器。确保已将 ADDR 设置为主机名或者环境中的服务器的 IP 地址。如果您运行的是一个大于 2.5 的 Python 版本,那么您可能会看到一个警告,但您不必担心这种情况。

我上面曾提到过,您必须提供自己的订户代理。简单的 HTTP 的妙处在于,它只需使用一条 cURL 命令就可以充当订户代理并订阅您的服务器来获得提要。参见 清单 2 中的命令。

清单 2. 使用 cURL 进行订阅
curl -v http://pubsubhubbub.appspot.com/subscribe \
-d hub.callback=http://$ADDR:8080/subscriber\&\
hub.topic=http://stackoverflow.com/feeds/tag/python\&\
hub.verify=sync\&hub.mode=subscribe\&hub.verify_token=\&hub.secret=

清单 2 中的 cURL 命令会联系 Google 的 hub,并订阅您的服务器,以获得 Stack Overflow 的 Web 提要中的某个主题。Stack Overflow 是一个社区站点,开发人员可以在此提出问题并讨论问题。我恰好知道 Stack Overflow 使用了 Google 的 hub,所以我不会为发现阶段感到烦恼,我只需为 Python 主题选择提要即可,这个主题相当活跃。如果一切进展顺利的话,您会从 cURL 中得到一个 HTTP 204 响应,此外,当 hub 与订户联系时,您还会在正运行的订户的控制台上看到一些调试信息。

现在,如果您等待一会 Python Stack Overflow 提要的更新,您将会发现已经使用内容更新了的订户。您可以再次使用 cURL 命令从 hub 看见一个简单的更新结构,例如以下命令: curl http://addr:8080/items

在这里,您可以使用您的订户服务器替换 addr,也就是说,该值与 ADDR 环境变量相同。

大约一个小时后,在我的案例中我发现了一个推向订户的条目,此条目表现您在 清单 3 中所见的一个结构。

清单 3. 已推出的条目
[{"content": "...",
"source": "http://stackoverflow.com/questions/9155264/xyz-question", 
"title": "XYZ Question",
"time": "2012-01-25 05:11:22.849931"}]

该条目的 HTML 表示形式出现在省略号所在的位置上。此结构使用 Python 编写很容易,或者可以将它转换为 JSON。就是这样,您就可以进行发布/订阅。


结束语

首先,PubSubHubbub 并不是您认为的最简单的协议,但无需花费太长时间您就能掌握它,认识到它有多强大,以及它对开放源码开发人员在 Web 上交流看法和代码有多重要。其他用户(包括商业机构)已经为 Google 的开放源码参考实现建立了分支,以形成其他 PuSH 实现的基础。目前,已经有适用于大量语言和平台的 hub 和订户实现,而且如果您不想自己运行代码,可以使用 Web 服务。不知不觉中,您就可以了解发布/订阅,既得乐趣,又得利益。

参考资料

学习

获得产品和技术

  • 了解 PubSubHubbub 并在程序主页上获取参考代码。
  • 获取 cURL,它是用于 Web 测试和脚本集成的终极工具。
  • 获取 IBM 产品评估试用版软件(可下载),并使用专为开发人员设计的软件改革您的下一个开源开发项目。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Open source, Linux
ArticleID=819243
ArticleTitle=了解 PubSubHubbub
publish-date=06012012