2013年7月30日星期二

EVERNOTE基于Thrift打造开放API接口



在2007年当我们开始计划Evernote服务的时候,我们就知道在发布服务的那一天就需要同时支持瘦客户端(象浏览器)和胖客户端。这一点促使我们在设计web用户界面之前就开始思考远程协议和客户端访问API接口,而不是拖到几个月之后将API接口架在已经存在网站服务上。

我们的应用对API访问接口提出了下面的需求:
1、跨平台。当我们08年2月份发布的时候,我们产品代码有服务器端JAVA、客户端是Win32(包括WinMobile) C++、客户端Obj-C Cocoa。
2、二进制数据效率高。客户同步的便条信息中包含上百幅嵌入图,总共有10M字节大小。我们需要API接口用将近15M的带宽传输15M的便条。
3、向上/向下兼容性。一旦有人在他的笔记本上安装了1.1版,我们就不想在我们每次扩展数据模型时强迫他们升级本地软件。
4、原生支持(本机绑定)。我们不想写针对每个客户端写大量解析/封装代码。这个费时又容易出错,也会使得3变得不切实际。
5、有标准可依或开源软件。所有事情同等对待。我们不想把服务API锁在一个商业产品上。
6、不要太大。我倾向于在每个移动客户端部署不超过1MB的文件,不要超过200个类。

我们花了几个月时间来研究和测试各种备选方案。XML-RPC 和SOAP 在某些领域(上面的1和5)很强。ZeroC的ICE 在别的领域(2和4)很强。我们也争论过是否自己写一个专用的协议。

一个朋友推荐我们看一下FaceBook最近开源的Thrift 框架。Facebook在内部用它在后端服务器之间传递消息,它们之间经常跨越程序语言的界线(如php到c++)。其他人好象也是用Thift做类似的事情:在后端服务器之间通信用。

我们寻求的跟上面这有一点不一样:这个框架可以用在服务器之间的通信中,但是也需要用在大量的客户端与服务器通过internet同步上。在那时候,Thrift是最适合我们需求:

1、跨平台。我们用Thrift的接口定义语言定义好数据模型和服务操作,然后用它提供的编译器为各种不同语言生成客户端和服务器端的数据结构和服务接口调用。
2、二进制数据效率高:如果我们指定二进制数据是1MB的数据,编码后在线路上传输的也就是1MB左右。
3、向上/向下兼容性:这是Thrift真正适用的地方。如果你足够细心并且明白thrift是如何工作的话,你就能在不影响现有的客户端的情况下增加数据结构、字段、服务方法和函数参数。3年前发布的Windows和Mac客户端在今天仍然能跟Evernote同步。
4、原生支持:在那个时候,Thrift没有包含任何Obj-C Cocoa支持,这样我们Mac组的一个同事把这个加到了Thrift编译器里。
5、标准支持或开源软件。Facebook已经把thrift交给了apache。
6、不要太大。Thrift运行库和生成的代码都很小,而且是直接了当。我能够很容易阅读和弄明白他们是如何工作的。(从那以后,它开始变得有点复杂,因为不同的贡献者添加了很多用例并作了一些优化,但是我要说,它跟其它方案比还是相当紧凑的)。

最后的结果是Evernote服务接口,这个让我们自己的客户(几百个第三方应用)使用原生代码跟一个通用的API访问接口打交道。我们有超过3百万的活跃用户,经常在不同的平台上使用evernote,我认为绝大多数运行Thrift代码的计算机设备是Evernote客户。

英文原文链接:
So API Together: Evernote and Thrift 

没有评论:

发表评论