Thrift是什么
apache thrift是一个在不同平台和语言间帮助建立可扩展,分布的系统。期初在Facebook内部开发,后来变为由apache基金会管理的开源项目,它以支持的语言多,松散,高性能著称。
分布式系统与服务
首先可以想象一下我们每天使用的web应用,比如说搜索引擎,消息平台,社交媒体等等。在一个web地址中,他们可以发送不同的服务。比如说,社交媒体实现人们的搜索,消息,用户信息页面。
面向服务的架构
我们这里以消息服务为例,相比于web应用来说,它可能会使用完全不同的语言。
- 页面开发和管理可能用到PHP或者Ruby on Rails
- 消息队列可能会采取使用Python,毕竟它的库非常的丰富
- 搜索引擎方面需要非常好的性能。可能会用到C++
- 架构的方面可能会使用C#或者Java
这些应用需要彼此调用。那么我们应该怎么做呢?在这里有一个软件概念叫SOA(service-oriented architecture)。在这里我们只关注前面部分,也就是面向服务。它作用于在不同的任务中创建应用。如果每一个任务需要被不同的应用启动的话,那么需要某些方法来调用他们。这样一些应用会提供一些服务来让其他应用调用。他们可以通过内部网络或者Internet来调用服务。同时它们的文档非常丰富,这样会方便其他用户调用。
分布系统
拿社交网络应用举例,它可能包含大量的自主服务。我们可以称之为分布系统(distributed systems)。这种系统可以部署在一个单一的机器,也可以部署在本地网络的多个机器中。因为其遵循SOA准则,所以你在可以本地进行测试,同时可以管理上百台机器。
管理维护
如果系统包含了许多应用,没有拥有一个任务或者一系列的任务而不是一个庞大的系统,一些的功能将会展示的更加简单:
- 你可以选择适合你解决任务的语言。
- 相比较于多个开发人员在一个项目中,你可以根据不同的任务来拆分组员,甚至一些功能采取外包的策略。
- 连接多个应用的功能只需要一些接口来实现,这样的对于排查错误,查看源码非常的方面。
- 更好的解决BUG或者失败。因为是分布式系统,各个部分是解耦的。如果存在某个功能crash了。可以让运维人员回滚到稳定版本,这样就不会影响其它的功能。
- 版本迭代说明非常简单。如果新的版本上线,只要将服务器部署新的版本,上线后,看线上回归是否正确,如果有问题,则回滚至上一版本。
扩展性
许多系统需要在高负载的状态下拥有良好的性能。这时就应该需要对系统进行扩展。
- 对于升级硬件的方案,我们称之为垂直扩展。
- 对于添加更多的机器(可以称之为节点【node】),我们称之为水平扩展。
在水平扩展系统中,可以根据系统的状态来进行扩展。比如说,一个大型的应用可能包含多个应用节点,多个数据阶段,多个用户搜索节点。开发人员可以根据系统当前的状态来添加或者删除节点;其中有些系统拥有自我扩展功能,他们可以根据当前服务器状态自动开启或者关闭相应的节点。
可测试性
分布式系统的另一点好处是测试的易用性和查找修改bug。系统的彼此独立表明他们可以在隔离整个系统中进行测试。
Apache Thrift 简介
Apache Thrift 诞生于这样一个现状,一个使用IDL文件可以自动生成不同语言的代码。在其他的解决方案中,数据要做预处理在发送之前来面对传输方法的限制--不是所有的结构是可以容易的传输的。在数据传输过成功,需要对文本进行序列化和反序列化,这些会增加额外的工作量,测试和debug。编程人员可以使用他们自己的编程语言类型,方法来实现传输,所有的序列化和反序列化都是Apache Thrift自己完成,并且对开发人员不可见。这样的解决方案的结构允许开发人员专注于实际的服务,而不是关系数据是怎么从一个应用传输到另一个。
支持的语言类型
支持的语言非常丰富,这里列举了其中常用的一些语言:
- ActionScript 3
- C++
- C#
- D
- Delphi
- Erlang
- Go
- Haskell
- Java
- JavaScript
- Node.js
- Objective-C/Cocoa
- OCaml
- Perl
- PHP
- Python
- Ruby
- Smalltalk
数据类型
基本类型为integer和string。
Apache Thrift会根据类型(强类型和弱类型)在传输过程中映射到最基本的类型。传输完成后,在接收方会转化为对应的类型。所以我们只需要关注于开发应用而不是接口连接。
传输
传输是Apache Thrift网络堆栈的一部分。允许你传输数据使用不用的通道,HTTP协议,sockets或者文件传输。解耦这些传输层能让你简单的选择最适合你的解决方案,而不需要修改代码。
协议
协议可以理解为把数据根据传输来序列化和反序列化。
我们可以采用不同的协议进行传输:json,二进制,纯文本等等。
这些取决于你想使用什么方法来实现,怎样来传输。
版本
版本是一个用来管理服务api修改的方法。开发人员不可能期望用户升级到最近版本,这样会导致了新旧版本迭代各个服务的兼容性问题。
有时候开发人员会有一些约定俗成,MAJOR,MINOR,PATCH。
- MAJOR-代表可能与以前软件版本不发生兼容
- MINOR-表示大的改动,但是不会影响与老的版本兼容
- PATCH-小改动
Apache Thrift的特性是软版本(soft versioning)。根据两个版本迭代修改如何处理或者声明没有正式的要求。
安全性
Apache Thrift 允许你使用TSSLTransportFactory来实现RSA键值配对。同时还可以使用ssh连接。
Interface description language(IDL)
这是它的核心,这样可以变得简单和可用。使用IDL文件,你可以在一个文件中定义服务和变量。
以下是一些简单的服务实例:
namespace py thrift.example1
namespace php thrift.example1
service AddService {
i32 add(1: i32 a, 2: i32 b),
}
保存文件,命名为example1.thrift。执行以下程序:
$ thrift --gen py example1.thrift
$ thrift --gen php example1.thrift
Apache Thrift 和其他RPC服务
自定义协议
当他想要在两个应用中传输数据,自定义协议应该为首选方法。
创建自己的协议其实很简单,只需要根据json或者XML格式生成数据,通过HTTP传输数据。在客户端,我们只需要连接到服务,拿到文本,之后解析即可。
比如说我们访问一个接口地址:GET /add?number1=30&number2=12
返回的结构:
{"result":42}
这些就完成了一些自定义的服务协议。
但是这样的协议也存在着一些缺点:
- 基本文本的协议有显著的开销,尤其是XML,它会压缩成许多个节点(tags)
- 在传输二级制文件的时候需要开销,因为协议是基于文本传输,所以这些文件需要转化为base64格式进行传输,这样文件的体积会增加37%。同时两边的处理也会增加额外的开销。
- 这种协议没有一定的标准。
- 维护也是一个难题。如果需要修改,服务器端和客户端都需要同时进行修改。
对于二级制文件来说,可以采取使用sockets,文件,队列或者其他的媒介。这样可以避免基于文本协议带来的问题,但是会有其他的问题产生。
XML-RPC 和JSON-RPC
两个都是RPC协议。早期使用的是基于XML编码通过HTTP传输。近年来使用JSON编码来代替XML。
以下是XML-RPC请求:
<?xml version="1.0"?>
<methodCall>
<methodName>add</methodName>
<params>
<param>
<value>
<int>30</int>
</value>
</param>
<param>
<value>
<int>12</int>
</value>
</param>
</params>
</methodCall>
以下是返回格式:
<?xml version="1.0">
<methodResponse>
<params>
<param>
<value>
<int>42</int>
</value>
</param>
</params>
</methodResponse>
JSON-RPC请求:
{"method": "add", "params": [30, 12], "id": 1}
JSON-RPC响应:
{"result": 42, "error": null, "id": 1}
两种协议开销是一样,同时它们很好实现。但是缺乏一定的标准,可能不适合传输二级制文件
SOAP 和 WSDL
SOAP是一个解决方法来解决一些自定义协议的问题,其中包含XML-RPC。它主要是用来在web service与客户端交换结构化信息。
SOAP是基于XML,拥有几个特定的层级。
以下是SOAP消息包含的元素:
- 信封(Envelope):这是消息的根元素,确定消息作为SOAP和定义它的结构
- 头部 :可选项。包含了一些额外的具体应用的控制信息来鉴定信息。
- 体 :消息体(响应)
- 错误 :可选元素。用来传递错误信息。它包含错误代码,描述和一些应用特定信息。
SOAP标准化可以轻易的debug。
但是SOAP也有它的缺点:连接到XML处理的开发,同时需要将二级制文件转化为文本格式。
RESTful APIs
web services是用来适应REST架构限制,这被称之为RESTful APIs。
相比较于SOAP来说,RESTful APIs是轻量级的。它们利用http方法来操作数据。
- GET 获取信息或者元素
- PUT 创建或者修改集合或者元素
- POST 在集合中创建一个新的元素
- DELETE 用来删除整个集合或者指定的元素
有点:简单,高效。可扩展,可缓存。
缺点:缺乏一定的标准。
何时使用Apache Thrift
如果应用规模很小的话,可以采取自定义的协议。当应用变得复杂之后,可以采用XML 或者JSON来解决。如果系统需要一些标准,这是可以采用SOAP或者WSDL。如果只是为了解决集合里面的一些元素,这样可以采用RESTful APIs。
如果想要高性能,同时还可以传输二级制数据,对于修改定义提供了一些松散型。这时就应该采用序列化或者RPC传输。