thrift | 青训营

99 阅读3分钟

Thrift概述

给chatgpt加了给示例的custom instructions,竟然这么详细。

Thrift(又称为Apache Thrift)是一种开源的跨语言服务开发框架,它由Apache软件基金会维护。Thrift旨在简化多语言之间的服务通信,并且使得跨平台的开发变得更加容易。

Thrift通过定义一个IDL(接口定义语言)文件来描述数据类型和服务接口,然后使用Thrift编译器生成各种编程语言的代码,这些代码包括了用于序列化和反序列化数据、网络通信和服务调用的功能。这种方式使得不同编程语言的应用能够无缝地进行通信和协作,因为它们共享了相同的数据结构和接口定义。

让我们来看一个简单的例子,假设你有一个服务需要在不同的编程语言之间通信,比如在Golang和Python之间。你可以使用Thrift定义数据结构和服务接口,然后编译生成对应的代码。以下是一个使用Thrift定义和使用服务的示例:

首先,在Thrift的IDL文件中定义数据结构和服务接口,比如 example.thrift

namespace go example
​
struct Person {
    1: required string name
    2: required i32 age
}
​
service ExampleService {
    void printPerson(1: Person person)
}

然后,使用Thrift编译器生成Golang和Python代码:

thrift --gen go example.thrift
thrift --gen py example.thrift

在生成的代码中,你可以在Golang中调用服务:

package main
​
import (
    "fmt"
    "git.apache.org/thrift.git/lib/go/thrift"
    "example"
)
​
func main() {
    transportFactory := thrift.NewTTransportFactory()
    protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
​
    transport, err := thrift.NewTSocket("localhost:9090")
    if err != nil {
        fmt.Println("Error opening socket:", err)
        return
    }
    transport = transportFactory.GetTransport(transport)
    defer transport.Close()
​
    if err := transport.Open(); err != nil {
        fmt.Println("Error opening transport:", err)
        return
    }
​
    client := example.NewExampleServiceClientFactory(transport, protocolFactory)
    
    person := example.NewPerson()
    person.Name = "Alice"
    person.Age = 30
​
    err = client.PrintPerson(person)
    if err != nil {
        fmt.Println("Error calling service:", err)
        return
    }
}

同时,你也可以在Python中调用服务:

from example import ExampleService
from example.ttypes import Person
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
​
transport = TSocket.TSocket('localhost', 9090)
transport = TTransport.TBufferedTransport(transport)
protocol = TBinaryProtocol.TBinaryProtocol(transport)
client = ExampleService.Client(protocol)
​
transport.open()
​
person = Person()
person.name = "Bob"
person.age = 25
​
client.printPerson(person)
​
transport.close()

这就是Thrift的基本概述。通过Thrift,你可以方便地在不同的编程语言中定义和使用服务接口,实现跨语言的通信。

ThriftIDL

基本类型

thrift不支持无符号类型,因为很多编程语言不存在无符号类型,比如java

  • byte: 有符号字节
  • i16: 16位有符号整数
  • i32: 32位有符号整数
  • i64: 64位有符号整数
  • double: 64位浮点数
  • string: 字符串

容器类型

集合中的元素可以是除了service之外的任何类型,包括exception。

  • list<\T>: 一系列由T类型的数据组成的有序列表,元素可以重复
  • set<\T>: 一系列由T类型的数据组成的无序集合,元素不可重复
  • map<K, V>: 一个字典结构,key为K类型,value为V类型

结构体(struct)

struct People {
     1: string name;
     2: i32 age;
     3: string sex;
}

枚举(enum)

enum Sex {
    MALE,
    FEMALE
}

异常(exception)

thrift支持自定义exception,规则和struct一样,如下:

exception RequestException {
    1: i32 code;
    2: string reason;
}

服务(service)

service HelloWordService {
     // service中定义的函数,相当于Java interface中定义的函数
     string doAction(1: string name, 2: i32 age);
 }

类型定义

typedef i32 Integer
typedef i64 Long

注意,末尾没有逗号或者分号

常量(const)

const i32 MAX_RETRIES_TIME = 10
const string MY_WEBSITE = "http://qifuguang.me";

末尾的分号是可选的,可有可无,并且支持16进制赋值

命名空间

namespace api

文件包含

include "global.thrift"

注释

thrift注释方式支持shell风格的注释,支持C/C++风格的注释,即#和//开头的语句都单当做注释,/**/包裹的语句也是注释。

可选与必选

thrift提供两个关键字required,optional,分别用于表示对应的字段时必填的还是可选的。例如:

struct People {
    1: required string name;
    2: optional i32 age;
}

表示name是必填的,age是可选的。

参考链接

www.jianshu.com/p/0f4113d6e…