AICon全球人工智能与机器学习技术大会周四开幕,点击查看完整日程>> 了解详情
写点什么

AtomServer:数据分发的发布动力

  • 2008 年 9 月 01 日
  • 本文字数:5327 字

    阅读完需:约 17 分钟

考虑这样一个场景:你为之工作的公司是由完全独立的站点组成的联邦,而且在各种不同平台上用了半打不同编程语言来实现。每个独立站点都有其自己的数据库与模式,被拥有不同技术集合的各个团队管理,分布在美国和欧洲的八个站点上。别忘了,公司还在扩张。

你的任务?使这些截然不同的系统能彼此之间方便快捷的共享关键数据。

你的设计准则是:

  • 高传输能力——该服务在启动后每天需要传送大约 1M 的数据块。
  • 事务的正确性——作为所有客户端数据的权威来源,该服务必须是精确的。
  • 弹性——当数据因格式变更而重新发布时,该服务必须能够方便地进行无缝升级。
  • 松耦合——对于如此多的系统,每个都必须能自我独立管理。
  • 可采纳——对于以各种语言 (Java、C#、PHP、Ruby 和 ColdFusion) 实现的客户端而言,采纳该系统的门槛必须足够的低。
  • 自适应性——该系统必须能够支持多种不同类型的数据并能按照需要进行扩展以增加数据类型。

一年之前,在我们俩服务的 Homeaway.com 公司,我们面对的正是以上问题。没过多久,我们就认识到了两条设计原则:首先,一个分布式的发布-订阅服务是应对子系统的弹性和松耦合的极佳选择;其次,对于需要高伸缩性、可扩展性和易采纳性的系统而言,构建 RESTful 服务(相对于 SOAP 等重量级协议而言)是自然之道。这两条原则直接将我们引向了 _Atom_——一个 RESTful 发布协议——以及一种名为 _Atom 存储 _ 的新型数据产生服务。我们去年一直都在为 Homeaway 实现 Atom 存储。我们从实际实现中抽取出了开源的 Atom 存储框架,命名为 AtomServer( http://www.atomserver.org ),本文将对其进行描述。

Atom

Atom 由两份规范组成: Atom 聚合格式,它基于 XML 定义了描述 web feeds 的语言; Atom 发布协议,它描述了检索和操纵 feeds 的一种 RESTful HTTP 协议。

Atom 被认为是 RSS(Rich Site Summary,富站点摘要)的接替者,后者通常包含了人为撰写的内容,比如博客条目。因此,一个 Atom 条目或 feed(XML 元素和属性)内部结构传达了诸如作者、语言、标题等发布内容的语义。可别被这一点给骗了;Atom 条目非常适合将所有类型数据作为有效负载进行传送。

Atom 条目是数据记录个体,Atom feeds 是条目的列表。因为 Atom 是 RESTful 协议,所以对资源的访问是通过对标识资源(这里指的是条目和 feeds)的 URI 执行 HTTP 方法来完成的。举例来说,获取一个博客条目的 feed 可能是通过对 http://your-atomserver/entries/myblog 这样的 URI 执行 GET 方法来完成的,而响应可能会是:

2007-04-14T20:00:39Z My Weblog First Post Chris Berry 2007-04-14T20:00:00Z 1234 Next Post Bryon Jacob 2007-05-01T17:00:00Z 1235

Atom 还支持可被应用于条目的类别概念。类别是任意的字符串标签,可被应用于条目,使其成为某个分组的一部分。然后,可修改 Feed URI 包含过滤功能——只从 feed 返回那些应用了特定类别的条目。

有些术语在 Atom 上下文中具有特殊含义。条目被组织成固定的两级层次结构:工作空间和集合。工作空间包含着一定数量的集合,集合包含着一定数量的条目。一个 feed 的 URI 由其工作空间和集合组成。

http://your-atom-server/workspace/collection

而一个条目的 URI 就由工作空间、集合和条目 id 来组成。这一标识符在包含该条目的集合内必须是唯一的:

http://your-atom-server/workspace/collection/entryid

像 RSS 一样,Atom 也为 web 聚合框架提供了基础。支持 Atom 的客户端有很多,包括浏览器,新闻阅读器,以及几乎每种流行语言中的可编程客户端。再加上,Atom 实际上是建立在 HTTP 与 XML 之上的一个精简约定集合,因此几乎任何支持 web 的编程平台都可以很容易地访问它。

扩展和分层协议

核心 Atom 协议描述了操纵 feed 和条目的基本操作,错误报告与处理的方法,并特别提供了扩展概念。Atom 扩展是可在 Atom XML 文件中出现的附加 XML 元素和属性,以及可被应用于 URI 的附加 HTTP 请求参数,它可被用来修改支持 Atom 的服务器的行为。两个重要的扩展是:

  • OpenSearch——定义了一个搜索协议,包括确定支持哪类搜索的服务器内省方法。一个支持 OpenSearch 的服务将会将搜索结果作为 Atom feed 返回,其中每个结果被表示为一个条目。
  • Feed 分页——为基于时间的数据提供了分页功能,定义了 Atom feeds 的下一页和上一页链接类型,这样客户端就能使用它在多页 Atom feed 中前后翻页。

或许最显而易见又影响深远的 Atom 应用就要数 GData了,它是 Google 用来访问它们服务数据的 Web API。GData 包含了核心 Atom 规范和 OpenSearch,以及为覆盖这些规范未涉及的附加特性而进行的大量扩展。

当你不再将 Atom 条目局限于博客与新闻 feed 等 web 内容,并将其扩展到一般性的数据管理时,你就得到了 Atom 存储;一个由互联 Atom 条目组成的通用数据存储,你可以用 Atom 发布协议来编辑它,用 OpenSearch 来搜索它。AtomServer 正是在这样的期望中成长起来的:利用这一策略实现对我们数据的分布式访问。

数据访问的分布式控制

使用 Atom 协议的好处之一就是其系统内含的分布式特性。在 AtomServer 里,我们将分页概念与向服务器轮询 feed 更新的机制相结合,限制了每次请求返回的条目数量。客户端最初从头请求 feed,接着按页请求数据,直到没有新数据。之后,客户端需要定期检查新数据(例如,在上次成功处理的数据之后,是否有新的一页数据传送?)

每次变更的时候,Atom 都会用一个递增的计数器来标记每一个条目,而客户端被要求为每个它请求的 feed 保存被处理的计数器的最后一值。在随后对 feed 的轮询时,下一页数据的起始位被设置成上一页的终止位。这一方法能够有效应对使用 AtomServer 来处理大容量、快速变化数据的场景。

当你不使用起始位“拉取”feed,它将默认从 0 开始。举例来说,

GET http://your-atom-server/widgets/acme

将返回 http://atomserver.org/namespaces/1.0/ 名字空间中一个名为 endIndex(终止位)的扩展标签作为这个 feed 的子元素。它将包含当前检索页的最后一个标志位:

as:endIndex 23</as:endIndex>

在下次轮询时,这个数字将被作为 start-index(起始位)查询参数传送:

GET http://your-atom-server/widgets/acme?start-index=23

当被请求页没有新数据了,服务器将会返回一个 304 NOT MODIFIED(304 未修改)响应。该信号表明,在请求下一页数据之前最好等待一段可配置的轮询间隔时间。

使用 POST 和 PUT 管理条目标识

在 Atom,每个条目在其所属工作空间和集合中都有一个 ID 是至关重要的——这三个部分加起来使条目的 URI 成为该条目的唯一标识符,将其与服务中的其它条目分别开来。AtomServer 支持使用两种不同 HTTP 方法创建新条目:POSTPUT

当条目是由POST方法创建时,所用的 URI 是该条目将要插入的集合的 URI。在这种情况下,AtomServer 将负责为新条目分配条目 id,并在响应体中将这个 id 返回给POST调用者。

POST http://your-atom-server/widgets/acme

取而代之,当条目是由 PUT 方法创建时,为条目分配 id 的责任就落到了完成 PUT 操作的客户端头上。PUT 要操作的 URI 就成了欲创建条目的 URI。

PUT http://your-atom-server/widgets/acme/1000.xml

现有条目更新是通过对该条目的 URI 进行 PUT 操作来完成的——从这种意义来说,使用 PUT 创建一个条目就好像是“延迟更新”。如果没有这样的条目,就创建它,否则就对该条目进行更新。

使用乐观并发性(Optimistic Concurrency)保证数据完整性

为了在高度分布的 Atom 世界里确保一致、可预见的数据,AtomServer 使用了乐观并发性(Optimistic Concurrency)管理对系统的写入。乐观并发性(Optimistic Concurrency)规定:AtomServer 的写入者必须知道他编辑资源的当前修订号,并且应当在假定他的写入操作可以完成的前提下来进行操作,但要优雅地处理其他人同时对该资源进行写入操作的情形。

例如,假设系统 A 和 B 同时想要更改某个数据 feed 中的 Acme 部件。A 先来到,它请求 Acme 部件 123 的当前表述:

GET http://your-atom-server/widgets/acme/123.xml

然后 feed 响应返回了如下的“编辑链接”。

于是现在 A 着手对 123.xml 的表述开始编辑。此时 B 来到并请求 123.xml 的当前版本,并得到了同样的响应。B 的编辑比 A 用时要短,因此 B 立即将更改写回了编辑链接:

PUT http://your-atom-server/widgets/acme/123.xml/2

操作成功,返回 200 OK(200 成功),让 B 知道其编辑已成功提交给 AtomServer。此时,A 完成了编辑并试图将其写入同一个编辑链接,但是由于 B 的编辑,修订号已经被改变了。因而,A 将会收到一个 409 CONFLICT(409 冲突)HTTP 错误,表示他尝试更新的资源自从他最近一次刷新其视图之后已被他人更改过了。遇到这种情况,A 应该再次 GET 这个资源,这次会获取一个新的编辑链接,然后重复这个过程。注意,这使得 A 在 B 已经改动后的 /widgets/acme/123.xml 的副本上进行编辑,因此系统避免了 A 盲目地覆盖 B 的变更。

在许多系统中,对给定数据集合将只有单个权威的写入者。在那些场景中,为了降低乐观并发性(Optimistic Concurrency)带来的开销,可通过将星号(*)作为修订序号来屏蔽乐观并发性(Optimistic Concurrency):

PUT http://your-atom-server/widgets/acme/123.xml/*

然而,使用这一特性记住一点非常重要:只适于客户端知道给定资源仅有一个写入者的情形。

类别查询

在 Atom 中,条目“类别”是由一对值来明确说明的:Scheme 和 Term。Scheme 实质上是类别的“名字空间”,而 Term 是这一名字空间中一个特定的值。

借用 GData 对 Atom 的扩展,AtomServer 支持一种特殊的 feed 语法,它可以让客户端基于应用于条目的“类别”来对 feed 进行过滤。比如,为了只获取 Acme 部件中被标记为“红”颜色的 feed,请求可能是这样的形式:

GET http://your-atom-server/widgets/acme/-/(urn:colors)red

如果指明了多个类别,只有满足全部指定类别(逻辑与)的条目能被接受。例如,

GET http://your-atom-server/widgets/acme/-/(urn:colors)red/(urn:size)big

将会返回所有大号、红色的Acme 部件。利用前缀表示法可指明使用“AND(与)”和“OR(或)”的任意类别组合:

GET http://your-atom-server/widgets/acme/-/OR/(urn:colors)red/AND/(urn:size)big/(urn:color)blue

这将返回所有要么是红色,要么是大号、蓝色的Acme 部件。客户端应该将这些feed 跟其它feed 一视同仁:它们跟没有类别的feed 一样同样可以被轮询与分页。

AtomServer

AtomServer 是实现 Atom 存储的一款现成实现。它是以 Java web 应用实现的,应该部属于任何 J2EE Serlet 容器中。幕后,AtomServer 使用了 Apache 的 Atom 协议开源实现—— Abdera ——处理 RESTful 动词与 Atom 的 XML 词汇。

就给现有应用加上 Atom 前端而言,Abdera 是一款极其出色的类库。与之相比,AtomServer 则是一个完整的 Atom 存储实现。它提供了开箱即用的存储和与 Atom 元数据(以及 Atom 条目本身内容)交互需要的所有组件。

AtomServer 的协议尽可能地借鉴了 GData 的设计。在某些场合我们做了一些轻微的调整,以进一步提高 URL 的可读性,简化查询结构,或者实现 GData 规范所未能涉及的特性。

AtomServer 在关系数据库中管理条目关联的所有 Atom 元数据;在关系数据库或文件系统中管理条目实际内容,这取决于你的具体需求。 AtomServer 自动地为你处理 Atom 协议相关的每个方面(URI 解释,解析 Atom 元素与扩展,更新时间戳,对条目分门别类),因此你只需要将改动发布到服务器并每隔一段时间轮询 feed 更新。

AtomServer 使用非常方便。它可以部署为一个简单的 WAR 文件,或者作为替代,部署为一个独立的服务器,运行于其内部嵌入的 Jetty 服务器上。大多数的应用都只需要很少的配置(一些用于配置 Atom 工作空间和内容存储的 Spring Bean)就可以用上 AtomServer 了。

结论

AtomServer 仍有一些重要、高级的特性我们还没有涉及到。这次就没有机会展开讨论了,在今后的文章我们将深入探讨:

  • Atom 类别自动标记器:一种方便的配置机制,用于创建或更新条目时对其进行“自动标记”。其中内置了 XPathAutoTagger,使得你能够“XPath”你的内容并根据条件将其与 Atom 类别关联。
  • 批处理操作:全面支持创建,更新或者删除等请求混合而成的“批处理”操作。
  • Feed 聚合:一种将来自不同集合或工作空间的不同条目聚合到一个条目的强大能力,使用了 ATom 类别。包括请求这些聚合 feed 的能力。因此它让你从与不同的 feed 打交道——自行在后端将信息联结起来——中解脱出来,你只需监听一个单一的聚合 feed,它将反映其内部任一部分的变化 。

AtomServer 是看得见摸得着的。它正运用在我们公司的实际生产环境中,每天处理着上百万的请求,存储着几百万的条目。构建于 Atom 这样的 RESTful 规范之上,同时利用诸如 GData 这样的现有服务的设计,保证了其构建根基是坚固的。我们希望你能下载一份拷贝,并告诉我们你的想法。你可以从这里得到它: http://www.atomserver.org ,只需简单的步骤它就能很好的为你工作。

查看英文原文 AtomServer – The Power of Publishing for Data Distribution


志愿参与 InfoQ 中文站内容建设,请邮件至 editors@cn.infoq.com 。也欢迎大家到 InfoQ 中文站用户讨论组参与我们的线上讨论。

2008 年 9 月 01 日 05:151240
用户头像

发布了 133 篇内容, 共 28.5 次阅读, 收获喜欢 1 次。

关注

评论

发布
暂无评论
发现更多内容

一文读懂区块链技术如何改变非洲贸易(上)

Geek_987812

腾讯、网易纷纷出手,火到出圈的元宇宙到底是个啥?

行者AI

游戏

免费分享Redis从入门到精通的优秀图书

Java入门到架构

Java 书籍

好未来 x StarRocks:全新实时数仓实践,深入释放实时数据价值

StarRocks

数据库 flink 实时数仓 好未来 StarRocks

为什么开发人员都不愿写 API 文档?

狐哥说技术

Postman Apifox 接口文档 接口管理

没有你,对我很重要|靠谱点评

无量靠谱

想聊天?自己搭建个聊天机器人吧!

百度大脑

人工智能 聊天 飞桨

gitlab ee 14.1稳定版安装教程

阿呆

gitlab

灰度发布框架nepxion discovery源码分析(I)

X

微服务 Spring Cloud 灰度发布 discovery

为什么BAT的程序员能月薪 20k ,而你一个月只能拿 6K 的低保?差别就在这!

白亦杨

Java 编程 程序员

微服务的大潮:《多维分析高性能架构设计》训练营,深入剖析Netty、Tomcat、Redis源码!

Java领路人

Java 编程 程序员 面试 架构师

盘点Java线程池配置的常见误区,你中了几个?

北游学Java

Java 多线程

结构化流-Structured Streaming(八-上)

数据与智能

spark 查询引擎 结构化思维

声网Agora 教育 aPaaS 灵动课堂升级:UI与业务逻辑分离,界面、功能自定义更灵活

声网Agora

在线教育 网络

手慢无!Boss直聘大厂内部面试真题整理(全彩版)流出!

程序员小毕

Java 程序员 架构 面试 分布式

河南平安,附最全自救锦囊

石云升

7月日更 郑州加油

有图,有代码,好理解,学习内存管理,mmap机制

奔着腾讯去

Linux 内存管理 Mmap 内存映射

【堡垒机】堡垒机到底有用不?国内哪家堡垒机好用?

行云管家

云计算 数据安全 堡垒机

质量基础建设一站式服务平台搭建

13823153121

注意:线程的执行顺序与你想象的可能不一样!

冰河

Java 程序员 并发编程 多线程 异步编程

优秀!百度技术官甩出SpringBoot全栈小册,GitHub星标92.5k

Java 编程 程序员

Pravega Flink connector 的过去、现在和未来

阿里云大数据AI技术

澳鹏看点 | 厉害了,3D点云语义分割

澳鹏Appen

人工智能 自动驾驶 语义分割 数据标注 3D点云

大型企业采购云管理平台的诉求分析-行云管家

行云管家

云计算 云安全 云管平台 云资源

我们都是那条流浪的小黄狗|靠谱点评

无量靠谱

《小马哥java项目实战》训练营培训小结

夏日

什么是共识?(生活篇)

趣链科技

基于机器学习的语音编解码器声网Agora Silver:支持超低码率下的高音质语音互动

声网Agora

RTE 技术详解 音频体验 AI Codec

论区块链技术如何赋能社交代币并打造创作者经济新局面

Geek_987812

光子是深度学习的未来!光子有望替代电子计算机加速神经网络计算

百度开发者中心

深度学习 最佳实践 方法论

手写归并排序算法

实力程序员

程序员 C语言 排序算法 实力 编程实战

数据cool谈(第2期)寻找下一代企业级数据库

数据cool谈(第2期)寻找下一代企业级数据库

AtomServer:数据分发的发布动力-InfoQ