zoukankan      html  css  js  c++  java
  • Thrift IDL

    Thrift IDL基于Thrift Types,并且考虑到Thrift Types的定义,Thrift IDL文件由Thrift代码生成器处理,为各种目标语言生成代码,以支持IDL文件中定义的结构和服务。

    一、Thrift类型系统(Thrift Types)
    Thrift类型系统致力于让程序员尽可能的使用原生数据类型,而不用关心他们所使用的编程语言。
    1、基本类型
    bool: A boolean value (true or false)
    byte: An 8-bit signed integer
    i16: A 16-bit signed integer
    i32: A 32-bit signed integer
    i64: A 64-bit signed integer
    double: A 64-bit floating point number
    string: A text string encoded using UTF-8 encoding
    注意没有无符号整数类型。这是因为在许多编程语言中没有无符号整数类型。

    2、特殊类型
    binary: a sequence of unencoded bytes
    这是上面所提到的字符串类型的一种特殊形式,用于提供与Java更好的互操作性

    3、结构体
    结构体定义一个通用对象。本质上等价于OOP语言中的类,但没有继承。结构体有一组强类型字段,每个字段具有唯一的名称标识符。字段可以具有在Thrift IDL中描述的各种注释(数字字段id、可选的默认值等)

    4、容器
    容器是强类型容器,在大多数编程语言中能映射到常用的容器类型。
    有三种容器类型:
    list:元素的有序列表。翻译成STL vector、Java ArrayList、脚本语言中的本机数组等
    set:唯一元素的无序集合。翻译成STL set、Java HashSet、Python中的set等。注意:PHP不支持集合,所以它与列表类似
    map:值的唯一键的映射。翻译成STL map、Java HashMap、PHP关联数组、Python/Ruby字典等,虽然提供了默认值,但是类型映射不是显式固定的,已经添加了自定义代码生成器指令,以允许在各种目标语言中替换自定义类型。
    容器元素可以是任何有效的Thrift类型。

    为了最大的兼容性,map的键类型应该是基本类型,而不是结构体或容器类型。有些语言不支持本地映射类型中的更复杂的键类型。此外,JSON协议只支持基类型的关键类型。

    5、异常
    异常在功能上等同于结构,除了它们在每个目标编程语言中适当地从本机异常基类继承,以便在任何给定语言中无缝地与本机异常处理集成。

    6、服务
    服务是使用Thirft类型定义的。服务的定义在语义上等同于在面向对象编程中定义接口(或纯虚拟抽象类)。Thrift编译器生成实现接口的全功能客户端和服务器代码桩(stubs)。

    服务由一组命名函数组成,每个函数都有一个参数列表和一个返回类型。

    注意,除了所有其他定义的Thrift类型之外,void是函数返回的有效类型。此外,可以向void函数添加oneway修饰符关键字,该函数将生成不等待响应的代码。注意,纯void函数将返回一个响应给客户端,该响应保证操作已经在服务器端完成。用oneway方法调用客户端只能保证请求在传输层成功。同一客户机的oneway方法调用可以由服务器在并行/乱序的情况下执行。

    二、Thrift接口描述语言
    1、Document
    每个Thrift文档包含0或更多的头,后面跟着0或更多的定义。
    [1] Document ::= Header* Definition*

    2、Header
    header是一个Thrift include,一个c++ include,或者一个名称空间声明。
    [2] Header ::= Include | CppInclude | Namespace
    (1) Thrift Include
    include使来自另一个文件的所有符号都可见(带有前缀),并将相应的include语句添加到为此Thrift文档生成的代码中。
    [3] Include ::= 'include' Literal
    (2)C++ Include
    c++ include中添加了一个自定义c++程序,包括用于这个Thrift文档的c++代码生成器的输出。
    [4] CppInclude ::= 'cpp_include' Literal

    3、Namespace
    名称空间(namespace)声明哪个名称空间(namespace)/包(package)/模块(module)等。此文件中的类型定义将为目标语言声明。名称空间范围指示该名称空间应用于哪种语言;“*”的范围指示名称空间适用于所有目标语言。
    [5] Namespace ::= ( 'namespace' ( NamespaceScope Identifier ) |
    ( 'smalltalk.category' STIdentifier ) |
    ( 'smalltalk.prefix' Identifier ) ) |
    ( 'php_namespace' Literal ) |
    ( 'xsd_namespace' Literal )

    [6] NamespaceScope ::= '*' | 'cpp' | 'java' | 'py' | 'perl' | 'rb' | 'cocoa' | 'csharp'

    4、Definition
    [7] Definition ::= Const | Typedef | Enum | Senum | Struct | Union | Exception | Service

    5、Const
    [8] Const ::= 'const' FieldType Identifier '=' ConstValue ListSeparator?

    6、Typedef
    类型定义为类型创建另一个名称。
    [9] Typedef ::= 'typedef' DefinitionType Identifier

    7、Enum
    枚举创建带有命名值的枚举类型。如果没有提供常量值,则第一个元素的值为0,或任何后续元素的值大于前一个值。所提供的任何常数值都必须是非负的。
    [10] Enum ::= 'enum' Identifier '{' (Identifier ('=' IntConstant)? ListSeparator?)* '}'

    8、Senum
    Senum(和Slist)现在已被弃用,应该用字符串替换它们。
    [11] Senum ::= 'senum' Identifier '{' (Literal ListSeparator?)* '}'

    9、Struct
    结构体是Thrift的基本组成类型。每个字段的名称必须在结构体中是唯一的。
    [12] Struct ::= 'struct' Identifier 'xsd_all'? '{' Field* '}'

    10、Union
    union类似于struct,只不过它们提供了一种方法来传输一组可能的字段,就像c++中的union{}一样。因此,联合成员被隐式地认为是可选的(请参阅require)。
    [13] Union ::= 'union' Identifier 'xsd_all'? '{' Field* '}'

    11、Exception
    异常与结构相似,除了它们旨在与目标语言中的本机异常处理机制集成。每个字段的名称必须在异常中是唯一的。
    [14] Exception ::= 'exception' Identifier '{' Field* '}'

    12、Service
    服务为Thrift server提供了接口。接口只是一个函数列表。服务可以扩展另一个服务,这仅仅意味着它除了提供自己的服务之外还提供扩展服务的功能。
    [15] Service ::= 'service' Identifier ( 'extends' Identifier )? '{' Function* '}'

    13、Field
    [16] Field ::= FieldID? FieldReq? FieldType Identifier ('= ConstValue)? XsdFieldOptions ListSeparator?

    14、Field ID
    [17] FieldID ::= IntConstant ':'

    15、Field Requiredness
    有两个显式的Requiredness值,第三个是应用的含义(如果既不是必需的也不是可选的):默认Requiredness。
    [18] FieldReq ::= 'required' | 'optional'

    Requiredness的一般规则如下:
    required
    Write: 字段总是被写入,并且期望被设置。
    Read: 字段总是被读取,并且期望包含在输入流中。
    Defaults values:总是被写入。

    如果在读取过程中缺少一个required字段,那么预期的行为是向调用者指出一个失败的读取操作,例如抛出异常或返回错误。

    由于这种行为,required字段极大地限制了软版本控制的选项。因为它们必须在读取时显示,所以不能废弃字段。如果需要的字段被删除(或更改为可选字段),则版本之间的数据不再兼容。

    optional
    Write: 字段只在设置时才写入。
    Read: 字段可能是,也可能不是输入流的一部分。
    Defaults values:在设置isset标志时被写入。

    大多数语言实现都使用所谓的“isset”标志,以指示是否设置了特定的可选字段。只有具有此标志的字段才被写入,相反,只有在从输入流读取字段值时才会设置标志。

    default requiredness (implicit)
    Write: 在理论上,字段总是被写入。这个规则有一些例外,见下文。
    Read: 与可选字段一样,字段可能是或不是输入流的一部分。
    Defaults values:可能不写(见下一节)

    默认需求是一个很好的起点。所期望的行为是可选的和必需的混合,因此内部名称为“opt-in, req-out”。虽然理论上这些字段应该是写出来的(“req-out”),但在现实中,未设置的字段并不总是写出来的。特别是当字段包含一个不能通过Thrift进行传输的值时。这一点的唯一方法是完全不编写这个字段,而这正是大多数语言所做的。

    默认值的语义(Semantics of Default Values)
    关于这个话题还有很多讨论。并不是所有的实现都以相同的方式处理默认值,但是当前的状态或多或少是默认字段通常在初始化时设置的。因此,可能不会写入等于默认值的值,因为读端将隐式地设置值。另一方面,无论如何,实现都可以自由地写入默认值,因为没有硬限制可以防止这种情况。

    这里要记住的主要一点是,任何未写入的默认值都隐式地成为接口版本的一部分。如果这个默认值改变了,那么接口就会改变。相反,如果将默认值写入输出数据,则IDL中的默认值可以随时更改,而不会影响序列化数据。

    16、Functions
    [21] Function ::= 'oneway'? FunctionType Identifier '(' Field* ')' Throws? ListSeparator?

    [22] FunctionType ::= FieldType | 'void'

    [23] Throws ::= 'throws' '(' Field* ')'

    17、Types
    [24] FieldType ::= Identifier | BaseType | ContainerType

    [25] DefinitionType ::= BaseType | ContainerType

    [26] BaseType ::= 'bool' | 'byte' | 'i8' | 'i16' | 'i32' | 'i64' | 'double' | 'string' | 'binary' | 'slist'

    [27] ContainerType ::= MapType | SetType | ListType

    [28] MapType ::= 'map' CppType? '<' FieldType ',' FieldType '>'

    [29] SetType ::= 'set' CppType? '<' FieldType '>'

    [30] ListType ::= 'list' '<' FieldType '>' CppType?

    [31] CppType ::= 'cpp_type' Literal

    18、Constant Values

    [32] ConstValue ::= IntConstant | DoubleConstant | Literal | Identifier | ConstList | ConstMap

    [33] IntConstant ::= ('+' | '-')? Digit+

    [34] DoubleConstant ::= ('+' | '-')? Digit* ('.' Digit+)? ( ('E' | 'e') IntConstant )?

    [35] ConstList ::= '[' (ConstValue ListSeparator?)* ']'

    [36] ConstMap ::= '{' (ConstValue ':' ConstValue ListSeparator?)* '}'

    19、基本定义
    Literal
    [37] Literal ::= ('"' [^"]* '"') | ("'" [^']* "'")

    Identifier
    [38] Identifier ::= ( Letter | '_' ) ( Letter | Digit | '.' | '_' )*

    [39] STIdentifier ::= ( Letter | '_' ) ( Letter | Digit | '.' | '_' | '-' )*

    List Separator
    [40] ListSeparator ::= ',' | ';'

    Letters and Digits
    [41] Letter ::= ['A'-'Z'] | ['a'-'z']

    [42] Digit ::= ['0'-'9']

  • 相关阅读:
    IIS 之 未能加载文件或程序集“IBM.Data.DB2”或它的某一个依赖项。试图加载格式不正确的程序。
    WebService 之 身份验证
    MVC 之 属性详解
    绕过Web授权和认证之篡改HTTP请求
    跨站点脚本编制-XSS 描述及解决方法
    CSRF(跨站请求伪造攻击)漏洞详解
    HTTP.SYS 远程执行代码漏洞分析(MS15-034 )
    Socket 之 传值方式
    GET 和 POST的区别
    Gdb调试多进程程序
  • 原文地址:https://www.cnblogs.com/danxi/p/9283636.html
Copyright © 2011-2022 走看看