代码改变世界

看看thrift 是怎么玩的

2012-03-14 17:53  xlw  阅读(731)  评论(0编辑  收藏  举报

1. 基本名词

     Types: 为了满足多语言平台的要求,需要提供基本数据类型来进行转换。比如在C++的Map和Python的Dict之间能够相互转换。

     Transport: 对于每一种语言,都应该有一个抽象的公共层来完成对应的双向数据传输。

     Protocal: 数据需要有一种方式来使用对应的传输层的code,而不用关心传输层的具体实现细节。

     Versioning:数据需要有自己的版本号来实现对应的健壮性。

     Processing : 产生code来完成RPC调用。

2. 类型

    1. Goals: 

         1. 使用最基本的数据类型,不管上层使用怎么样的编程语言。

         2. 不使用动态数据类型,也不需要开发者写对象序列化或者传输的代码(已经封装)。

         3. IDL 用来告诉代码生成器如何在多语言之上安全地传输数据。

    2. Base Types:

         1. 选取了大多数语言中都存在的基本数据类型,忽略了一些语言中特别的类型。(无符号类型), 所有的基本

            类型都是有符号的。

         2. 基本类型包括bool, byte,i16,i32,i64,double,string。

    3. Structs:

          1.   提供了一种common的对象来代表面向对象语言中的对象类型,每一个filed都有一个标志符。

          2.   每个filed必须有一个标志符和一个给定的默认值。标志符如果没有给定的话,会自动分配一个,但是强烈建议给定标志符,为了方便版本控制。

     4. Container:

          1.  List, set, Map。其中List被翻译成STL中的vector, 或者Java中的ArrayList,set和map类似。

          2.  要求对应的基本语言类型支持对应的Thrift的基本数据类型。

          3.  在每一种目标语言中,对于每一种定义的类型,生成两个接口,read和write,用于序列化和传输对应的数据结构。

     5. Exceptions:

          1. 使用Exception关键字来代替对应的structs关键字,得到对应的基本类。

          2. 生成的对象继承自每一种语言中的对应的Exception的基类。

     6. Services:

           1. 提供了服务端的接口调用,通过代码生成器会生成Client端和Server端的桩函数接口,共上层调用使用。

           2. 在每一个函数前面可以加上async关键字,这个关键字能够实现对应的一部方法。

           3. 一个纯void函数也会返回一个response,用来保证该操作在服务端已经被执行。

           4. async call只保证消息在传输层是没有问题的,因此,在使用async的时候需要保证当前的使用环境对于丢包是可以接受的。

3. Transport

      1. 接口

            1. 传输层用来促进数据传输。一个关键的设计是Thrift将数据传输层和代码生成器分开。

            2. 由于抽象的IO炒作产生的tradoff相比起实际的IO操作显得微不足道。

            3. 需要满足的基本功能:如何读写数据,不管是在网络中,还是共享内存,还是从磁盘文件中读写。

            4. 提供的接口如下:open, close,isOpen, read, write, flush。还有一些用于batch操作的接口

            5. 对于TServerTransport,还有接口用来创建对应的Transport对象。如open, listen, accept, close。

       2. 实现

            1. TSocket 类对于TCP/IP的流式套接字实现了一个通用,简单的接口。

            2. TFileTransport类实现了一个抽象接口,用于将磁盘文件导入到数据流中。

       3. Utilities

            1. 网络传输层设计的支持简单的扩展,比如组合,TBufferdTransport实现在传输层实现了buffer的功能,TFrameTransport实现了数据头定长大小,用于Noblocking传输。TMemoryBuffer允许读和写直接在进程的堆顶完成。

4. Protocal

         1. 接口

               1. 另外一块主要的部分是thrift中将数据结构和传输层分离,thrift定义了一些传输时的基本类型,但是没有强制定义需要实现的编码格式,只要能被代码生成器识别就好。

                2.  thrift协议的接口简单明了,支持两种功能:双向有序的消息,基本类型,容器,结构的编码。

         2. 结构

                1. Thrift中默认使用流式结构来传输对应的协议,这样避免了因为需要分片或者在发送前整体计算带来的性能损失。当有的场景需要使用分片,或者分片的性能优势更加明显的时候,可以使用TFramedTransport这个抽象接口类。

         3. 实现

                 1. Thrift的实现了一个空间高效的二进制协议,所有的数据都以一个扁平的二进制格式存在,整形被转换为网络字节序,字符串在头上加上它的长度,所有的消息和field 头都用它的整数序列号,忽略这些filed中的字符串名字。

                 2. 我们没有做过多的性能优化,为了代码的整洁和高效。如果有需要,可以加入这些优化方案。

5.Versioning

       1. 域标志符

            1. Thrift在版本控制上面是健壮的,它可以接受旧客户端过来的请求并正确处理。

            2. Thrift中的版本控制是通过域标志符来确定的,thrift结构中的每一项前面都有一个对应的标志符,标志符和数据类型唯一化开item。

            3. 为了避免冲突,自动分配的标志符从-1开始递减,人工定义的标志符只能为整数。

            4. 在数据是自定义的前提下,当反序列化的时候,thrift的code 生成器可以根据标识符来判断读取到的数据是否对齐,也可以跳过不能识别的域,保证兼容性。

            5. 域标志符也可以在参数列表中声。

       2. Isset

             1. 用来标注必须存在于结构体中的域,如果必须存在,标注为true,这样可以当该域不存在的时候,可以通知上层调用者。

        3. 场景分析

              1. 4种场景,加减域/新旧client或者server。

         4. Protocal/Transport Versioning

               1. 实现了TProtocal的抽象接口,用来让协议的实现自己来管理版本。

6. RPC 实现

        1. TProcessor

                1. 核心类,抽象出client和server的基类,核心功能是处理input和output。

        2. Generated code

                 2. 自动生成client端和server端的调用接口。

        3. TServer

                 1. Tserver 可以有多种实现,来满足不同的需求。如单线程的TSimpleServer, 每个连接一个线程的TThreadedServer, 还有基于线程库的TThreadPoolServer.

                 2. 开发者可以实现自己的TServer。

7. 实现细节

         1. 目标语言

                1. C++, Java, Python, Ruby, PHP

                2. 尽可能简单的抽象,保留在每一种语言中可以自主开发的空间。

         2. 生成的结构体

         3. RPC 方法定义

                1. RPC call中的方法用string去实现,用一些手段将字符处理的代价尽可能的减少,同时方便编程实现。

         4. 服务器和多线程

                1. 因为种种原因,没有采用boost的线程库,也没有采用ACE,自己实现了一套机制。

          5. 线程模型

                1. thfirt的线程库包括三个部分:primitives, thread pool manager, timer manager

                2. 每个线程是一个对象,提供了Runnerable接口供使用,Synchronized关键字实现类似java的同步块功能。

           6. Thread,Runnable, and shared_ptr

           7. ThreadManager

           8. TimeManager

           9. NonBlocking Operation

           10. 编译器

           11. TFileTransport

8. Facebook thrift service

           1. Search&&logging

                1. TFileTransport可以实现对应的结构化logging, 这个logging日志可以用来做线上和线下的处理,可以作为redo log。