在 OSCON '08 大会上, Evan ‘Rabble’ Henshaw-Plath 和 Kellan Elliott-McCrea 介绍了《超越REST?使用XMPP PubSub 构建数据服务》。 Robert Kaye 对该幻灯片的报道如下:
Kellan 谈到了 FriendFeed ,它是一个让使用者知道他们的朋友共享了新项目的网站。在这个例子中,Kellan 指出:为了给 45000 名使用者检查更新,FriendFeed 向 Flickr 轮询了 290 万次。而且在这 45000 名使用者中,在任意时刻只有 6700 名处于已登录状态。这当然是一种蹩脚的内容更新检查方式。Kellan 说道:“轮询太逊了!”
解决这个问题的关键在于将标准 REST Web 服务抛在脑后,找出一种使用消息传递的方式,它是一种通知使用者内容变更的直接通信方式。
在这个上下文中,轮询意味着使用一种RESTful Web 服务来为每个使用者获得(GET)更新。与之相反, PubSub (Publish/Subscribe,发布 / 订阅)是一种使用异步消息传递协议的架构性方法,其中发布者和任何订阅者都是解耦的。在需要向大量客户端发送更新通知的场合下,这些特征使得 PubSub 成为一种合适的可伸缩性选择。
在这个幻灯片中,Evan 和 Rabble 描述了 Jabber (一种基于 XMPP [Extensible Messaging and Presence Protocol,可扩展消息传递和现场协议] 的 PubSub 服务)的各种优势:
- XMPP 工作在持久化连接之上
- 它是有状态的(SSL 变得便宜)
- 被设计成为一个事件流协议
- 联邦和异步的天性
- 内置身份认证、安全和现场(presence)
- 为此构建和部署了 Jabber 服务器
该幻灯片引起了巨大反响。 Kirk Wylie 认为像 AMQP 这样的基于 MOM (Mesage Oriented Middleware,面向消息的中间件)的系统才是这儿真正需要的,而 Joshua Schacter (del.icio.us 创始人)也加入了论战的行列,并指出了一种更简单的方法。这个方法使用基于 HTTP 回调的技术:
简而言之,与频繁地轮询不同,客户端可以发送一个包含欲订阅资源(resouce)和交付更新的端点(endpoint)的普通 HTTP 请求到:
http://your.app/subscribe?resource=/some/user&callback=http://my.app/endpoint
这样推断,端点当且仅当资源更新时才会收到 RSS 条目片断。出于安全考虑,交换要包含某种令牌,它可向合适的协议借鉴。订阅将在一段时间后失效,比方说,24 小时,或将其作为一个参数传入。
Rabble 提供了他关于使用回调的思考:
那么,这里有两个问题,我们曾经考虑加入一页幻灯片来讨论 ping back 系统。显然,能够进行 ping back/web hook 似乎是个好模式,但也可能是反模式?
可以预见,创建一个大规模 web hook 系统,你将面临聚合器(aggregator)/ 爬行器(crawler)问题。使用 XMPP 绝对可行。这样,我们不仅实现了联邦功能,而且有着更好的接口。我们还有潜力可在其之上增加一些代理认证(auth)功能。
诸如 Webhooks 这类方法潜在地要比使用 Jabber/XMPP 简单得多,但是 Blaine Cook 认为这种复杂性是说得通的:
如果我们声称只需 10 行 PHP 脚本就可让系统可用,那么这一过程只能得到一个实现拙劣的输出消息队列。在中等规模(10000 使用者,每人有 50 个联系人,1/5 离线,每天 2 个帖子)情况下,你会看到每秒有 2.3 个远程 HTTP 请求,这种方法倒也并非一无是处。
尽管使用 PubSub 进行通知是一个优秀的架构方法,但是很多人对幻灯片的标题存有疑问。 Dare Obasanjo 对此概括得非常好,指出 REST 并非一个“金锤”(译注:比喻,意指手拿锤子,看到任何东西都是钉子。):
[因而],这个例子并非是指 REST 象 Evan 和 Kellan 的讲演标题暗示的那样不能进行伸缩,而是一个使用错误工具解决问题的例子。选择它的原因在于它碰巧能在其他场合很好的工作。
即使没有其他内容,这次讨论也突现了这一事实,考虑 API 消费者的使用模式在确定合适设计的过程中扮演了举重轻重的角色。
评论