编写服务说明.thrift文件

1.数据类型

  • 基本类型:
    • bool:布尔值,true 或 false,对应 Java 的 boolean
    • byte:8 位有符号整数,对应 Java 的 byte
    • i16:16 位有符号整数,对应 Java 的 short
    • i32:32 位有符号整数,对应 Java 的 int
    • i64:64 位有符号整数,对应 Java 的 long
    • double:64 位浮点数,对应 Java 的 double
    • string:utf-8编码的字符串,对应 Java 的 String
    • 注意,thrift不支持无符号整型,因为很多目标语言不存在无符号整型(如java)。
  • 结构体类型:
    • struct:定义公共的对象,类似于 C 语言中的结构体定义,在 Java 中是一个 JavaBean
  • 容器类型:
    • list:对应 Java 的 ArrayList
    • set:对应 Java 的 HashSet
    • map:对应 Java 的 HashMap
  • 异常类型:
    • exception:对应 Java 的 Exception
  • 服务类型:
    • service:对应服务的类

2.命名空间
Thrift中的命名空间同C++中的namespace和java中的package类似,它们均提供了一种组织(隔离)代码的方式。因为每种语言均有自己的命名空间定义方式(如python中有module),thrift允许开发者针对特定语言定义namespace,如下示例:
namespace java com.example.project 
说明:转换成package com.example.project

3. 文件包含
Thrift允许thrift文件包含,用户需要使用thrift文件名作为前缀访问被包含的对象,如:
include "tweet.thrift"  
...
struct TweetSearchResult {
1: list<tweet.Tweet> tweets; // b
}

说明:
a.  thrift文件名要用双引号包含,末尾没有逗号或者分号
b.  注意tweet前缀

4. 常量
Thrift允许用户定义常量,复杂的类型和结构体可使用JSON形式表示。
const i32 INT_CONST = 1234;   
const map<string,string> MAP_CONST = {"hello": "world", "goodnight": "moon"}

说明: 分号是可选的,可有可无;支持十六进制赋值。

5. 定义结构体
结构体由一系列域组成,每个域有唯一整数标识符,类型,名字和可选的缺省参数组成。如:
struct Tweet {
1: required i32 userId;                  // a
2: required string userName;             // b
3: required string text;
4: optional Location loc;                // c
16: optional string language = "english" // d
}
struct Location {                            // e
1: required double latitude;
2: required double longitude;
}
说明:

a.  每个域有一个唯一的,正整数标识符
b.  每个域可以标识为required或者optional(也可以不注明)
c.  结构体可以包含其他结构体
d.  域可以有缺省值
e.  一个thrift中可定义多个结构体,并存在引用关系

规范的struct定义中的每个域均会使用required或者optional关键字进行标识。如果required标识的域没有赋值,thrift将给予提示。如果optional标识的域没有赋值,该域将不会被序列化传输。如果某个optional标识域有缺省值而用户没有重新赋值,则该域的值一直为缺省值。
与service不同,结构体不支持继承,即,一个结构体不能继承另一个结构体。

6. 定义服务
在流行的序列化/反序列化框架(如protocol buffer)中,thrift是少有的提供多语言间RPC服务的框架。
Thrift编译器会根据选择的目标语言为server产生服务接口代码,为client产生桩代码。
//“Twitter”与“{”之间需要有空格!!!
service Twitter {
// 方法定义方式类似于C语言中的方式,它有一个返回值,一系列参数和可选的异常 列表. 注意,参数列表和异常列表定义方式与结构体中域定义方式一致.
void ping(),                                    // a
bool postTweet(1:Tweet tweet);                  // b
TweetSearchResult searchTweets(1:string query); // c
// ”oneway”标识符表示client发出请求后不必等待回复(非阻塞)直接进行下面的操作, ”oneway”方法的返回值必须是void
oneway void zip()                               // d
}
说明:
a. 函数定义可以使用逗号或者分号标识结束
b. 参数可以是基本类型或者结构体,参数是只读的(const),不可以作为返回值!!!
c. 返回值可以是基本类型或者结构体
d. 返回值可以是void
注意,函数中参数列表的定义方式与struct完全一样
Service支持继承,一个service可使用extends关键字继承另一个service

7.概念
Thrift的网络栈如下所示:

7.1   Transport
Transport层提供了一个简单的网络读写抽象层。这使得thrift底层的transport从系统其它部分(如:序列化/反序列化)解耦。以下是一些Transport接口提供的方法:open、close、read、write、flush等,
除了以上几个接口,Thrift使用ServerTransport接口接受或者创建原始transport对象。正如名字暗示的那样,ServerTransport用在server端,为到来的连接创建Transport对象。ServerTransport 提供以下接口:
open、listen、accept、close。

7.2   Protocol
Protocol抽象层定义了一种将内存中数据结构映射成可传输格式的机制。换句话说,Protocol定义了datatype怎样使用底层的Transport对自己进行编解码。因此,Protocol的实现要给出编码机制并负责对数据进行序列化。

7.3   Processor
Processor封装了从输入数据流中读数据和向数据数据流中写数据的操作。读写数据流用Protocol对象表示。Processor的结构体非常简单:
interface TProcessor {
bool process(TProtocol in, TProtocol out) throws TException
}
与服务相关的processor实现由编译器产生。Processor主要工作流程如下:从连接中读取数据(使用输入protocol),将处理授权给handler(由用户实现),最后将结果写到连接上(使用输出protocol)。 7.4   Server
Server将以上所有特性集成在一起:
(1)  创建一个transport对象
(2)  为transport对象创建输入输出protocol
(3)  基于输入输出protocol创建processor
(4)  等待连接请求并将之交给processor处理

8. 应用举例
下面,我们讨论thrift文件产生的特定语言代码。下面给出thrift文件描述:
namespace cpp thrift.example
namespace java thrift.example

enum TweetType {
TWEET,
RETWEET = 2,
DM = 0xa,
REPLY
}

struct Location {
1: required double latitude;
2: required double longitude;
}
struct Tweet {
1: required i32 userId;
2: required string userName;
3: required string text;
4: optional Location loc;
5: optional TweetType tweetType = TweetType.TWEET;
16: optional string language = "english";
}
typedef list<Tweet> TweetList

struct TweetSearchResult {
1: TweetList tweets;
}
const i32 MAX_RESULTS = 100;

service Twitter {
void ping(),
bool postTweet(1:Tweet tweet);
TweetSearchResult searchTweets(1:string query);
oneway void zip()
}

(1) Java语言
(a)  产生的文件
一个单独的文件(Constants.java)包含所有的常量定义。
每个结构体,枚举或者服务各占一个文件
$ tree gen-java
`– thrift
`– example
|– Constants.java
|– Location.java
|– Tweet.java
|– TweetSearchResult.java
|– TweetType.java
`– Twitter.java
(b)  类型
thrift将各种基本类型和容器类型映射成java类型:
bool: boolean
byte: byte
i16: short
i32: int
i64: long

double: double
string: String
list<t1>: List<t1>
set<t1>: Set<t1>
map<t1,t2>: Map<t1, t2>
(c)  typedef
Java不支持typedef,它只使用原始类型,如,在上面的例子中,产生的代码中,TweetSearchResult会被还原成list<Tweet> tweets
(d)  Enum
Thrift直接将枚举类型映射成java的枚举类型。用户可以使用geValue方法获取枚举常量的值。此外,编译器会产生一个findByValue方法获取枚举对应的数值。
(e)  常量
Thrift把所有的常量放在一个叫Constants的public类中,每个常量修饰符是public static final。

参考资料: http://dongxicheng.org/search-engine/thrift-guide/

时间: 2024-09-30 16:19:25

编写服务说明.thrift文件的相关文章

2.thrift文件基本编写规则

thrift文件的基本数据类型 The first thing to know about are types. The available types in Thrift are: bool        Boolean, one byte byte        Signed byte i16         Signed 16-bit integer i32         Signed 32-bit integer i64         Signed 64-bit integer do

基于RMI服务传输大文件的完整解决方案

基于RMI服务传输大文件,分为上传和下载两种操作,需要注意的技术点主要有三方面,第一,RMI服务中传输的数据必须是可序列化的.第二,在传输大文件的过程中应该有进度提醒机制,对于大文件传输来说,这点很重要,因为大文件的传输时间周期往往比较长,必须实时告知用户大文件的传输进度.第三,针对大文件的读取方式,如果采用一次性将大文件读取到byte[]中是不现实的,因为这将受制于JVM的可用内存,会导致内存溢出的问题. 笔者实验的基于RMI服务传输大文件的解决方案,主要就是围绕以上三方面进行逐步解决的.下面

Spring Cloud下使用Feign Form实现微服务之间的文件上传

背景 ? Spring Cloud现在已经被越来越多的公司采用了,微服务架构比传统意义上的单服务架构从复杂度上多了很多,出现了很多复杂的场景.比如,我们的产品是个app,支持第三方登录功能,在手机端调用第三方授权接口之后,返回了用户的相关信息,比如open_id,性别,头像等.这些信息我们需要保存在我们服务器上,当时针对头像是应该保存图片的url还是图片本身发生了歧义,在一番讨论之后,得出的结果是,我们需要通过url将图片下载到我们本地,然后调用我们自己的文件微服务中上传功能保存起来. 工具 I

rpc服务框架thrift介绍

rpc服务框架目前主要有 thrift, grpc, dubbo, HSF等 这里主要介绍thrift框架 git地址  :https://github.com/apache/thrift/tree/0.9.1 1. 接口定义 tutorial.thrift include "shared.thrift" /** * Thrift files can namespace, package, or prefix their output in various * target langu

通过Java WebService接口从服务端下载文件

一. 前言 本文讲述如何通过webservice接口,从服务端下载文件.报告到客户端.适用于跨系统间的文件交互,传输文件不大的情况(控制在几百M以内).对于这种情况搭建一个FTP环境,增加了系统部署的复杂度和系统对外暴露的接口.通过在服务端读取文件,返回字节流到客户端的方式比较简单. 下面采用restful的接口形式,满足SOA架构接口要求.如下代码拷贝到eclipse中即可运行,功能自测试运行正常.样例代码的服务端和客户端在同一台PC上运行,放到不同PC上运行改一下发布服务和请求服务的IP地址

Linux网络服务04——FTP文件传输服务

Linux网络服务04--FTP文件传输服务 一.FTP连接及传输模式 1.控制连接:TCP 21,用于发送FTP命令信息 2.数据连接:TCP 20,用于上传.下载数据 3.数据连接的建立类型: (1)主动模式:服务器主动发起数据连接 首先由客户端向服务端的21端口建立FTP控制连接.当需要传输数据时,客户端以PORT命令告知服务器"我打开了某端口,你过来连接我",预算服务器从20端口向客户端的该端口发送请求并建立数据连接. (2)被动模式:服务器被动等待数据连接 如果客户端所在网络

django之创建第3个项目:编写第一个模板文件

1.django结构 2.在站点blog下创建templates文件夹,专门用于存放模板文件 3.在templates文件夹下创建index.html文件 #index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>第一个模板文件</title> </head> <body&

通过WebSocket实现实时通讯C#语言编写服务端

无意中发现js有webSocket对象于是百度了一下客户端代码与服务端代码没有现成的 有的就有一些简单了连接例子有的还不好使 于是就自己整理了一下 c#编写的服务端代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Text.RegularExpression

编写程序实现读取文件前几行

1 #编写程序实现读取文件前几行 2 def print_line(file_name): 3 line = int(input('请输入要显示前几行:')) 4 f = open(file_name) 5 for each_line in range(0,line): 6 print(f.readline()) 7 8 file_name = input('请输入要打开的文件名:') 9 print_line(file_name)