热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Thrift入门指南

一、内容概要Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目。Thrift通过一个中间

一、内容概要
          Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目。Thrift通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和数据类型,然后通过一个编译器生成不同语言的代码(目前支持C++,Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk和OCaml),并由生成的代码负责RPC协议层和传输层的实现。         
          上一篇文章着重讲解关于thrift框架的介绍。本文主要讲述的对象是thrift文件,及其client和server的编写方法。

二、Thrift语法
1. Thrift类型

Thrift类型系统包括预定义基本类型,用户自定义结构体,容器类型,异常和服务定义
(1) 基本类型

bool:布尔类型(true or value),占一个字节
byte:有符号字节
i16:16位有符号整型
i32:32位有符号整型
i64:64位有符号整型
double:64位浮点数
string:未知编码或者二进制的字符串


注意,thrift不支持无符号整型,因为很多目标语言不存在无符号整型(如java)。
(2) 容器类型
Thrift容器与类型密切相关,它与当前流行编程语言提供的容器类型相对应,采用java泛型风格表示的。Thrift提供了3种容器类型:
list:一系列t1类型的元素组成的有序表,元素可以重复。相当于Java中的List
set:一系列t1类型的元素组成的无序表,元素唯一。相当于Java中的Set
map:key/value对(key的类型是t1且key唯一,value类型是t2)。相当于Java中的Map
容器中的元素类型可以是除了service意外的任何合法thrift类型(包括结构体和异常)。
(3)  结构体和异常
Thrift结构体在概念上同C语言结构体类型—-一种将相关属性聚集(封装)在一起的方式。在面向对象语言中,thrift结构体被转换成类。结构体使用struct关键字声明。
异常在语法和功能上类似于结构体,只不过异常使用关键字exception而不是struct关键字声明。但它在语义上不同于结构体—当定义一个RPC服务时,开发者可能需要声明一个远程方法抛出一个异常。
结构体和异常的声明将在下一节介绍。
(4)  服务
服务的定义方法在语法上等同于面向对象语言中定义接口。Thrift编译器会产生实现这些接口的client和server桩。具体参见后面的部分。


2. 枚举类型

enum NewsType {TOPNEWS, //aSPORTS = 2, //bTECNOLOGY = 3,NBA = 0xa, //cEDU = 5
} //dstruct News { 1: i32 id; 2: string title; 3: string content; 4: string source; 5: string author; 6: double score;7: i64 readNum;8: NewsType newsType = NewsType.SPORTS; //e
}



说明:
a.  编译器默认从0开始赋值
b.  可以赋予某个常量某个整数
c.  允许常量是十六进制整数
d.  末尾没有逗号
e.  给常量赋缺省值时,使用常量的全称
注意,不同于protocol buffer,thrift不支持枚举类嵌套,枚举常量必须是32位的正整数

2.3. 注释
Thrfit支持shell注释风格,C/C++语言中单行或者多行注释风格

# This is a valid comment./** This is a multi-line comment.* Just like in C.*/// C++/Java style single-line comments work just as well.


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

namespace cpp com.example.project // a
namespace java com.example.project // b
namespace py com.example.project //python
namespace php com.example.project //php


说明:
a.转化成namespace com { namespace example { namespace project {
b.转换成package com.example.project
2.5. 文件包含
Thrift允许thrift文件包含,用户需要使用thrift文件名作为前缀访问被包含的对象,如:


namespace java com.example.thrift.serviceinclude "NewsModel.thrift" //aservice DataSource { string helloWorld(1: string name), bool indexNews(1: NewsModel.News indexNews), //bNewsModel.News getNewsById(1: i32 newsId), map getNewsMap(1: i32 newsType), list getNewsList(1: i32 newsType),
}



说明:
a.thrift文件名要用双引号包含,末尾没有逗号或者分号
b.注意NewsModel前缀,IDL文件名作为前缀,而不是命名空间

2.6. 定义结构体
结构体由一系列域组成,每个域有唯一整数标识符,类型,名字和可选的缺省参数组成。如:

struct News { 1: required i32 id; //a2: required string title; //b3: string content; 4: string source; 5: string author; 6: double score = 4.2; //d7: i64 readNum;8: NewsType newsType = NewsType.SPORTS;10: optional User user; //c
} struct User { //e1: required i32 id; 2: required string userName;3: required string password;4: optional string nickName;
}



说明:
a.每个域有一个唯一的,正整数标识符
b.每个域可以标识为required或者optional(也可以不注明)
c.结构体可以包含其他结构体
d.域可以有缺省值
e.一个thrift中可定义多个结构体,并存在引用关系
规范的struct定义中的每个域均会使用required或者optional关键字进行标识。如果required标识的域没有赋值,thrift将给予提示。如果optional标识的域没有赋值,该域将不会被序列化传输。如果某个optional标识域有缺省值而用户没有重新赋值,则该域的值一直为缺省值。
与service不同,结构体不支持继承,即,一个结构体不能继承另一个结构体。
2.7.  定义服务
在流行的序列化/反序列化框架(如protocol buffer)中,thrift是少有的提供多语言间RPC服务的框架。
Thrift编译器会根据选择的目标语言为server产生服务接口代码,为client产生桩代码。

namespace java com.example.thrift.serviceinclude "NewsModel.thrift"
//“DataSource”与“{”之间需要有空格!!!
service DataSource { string helloWorld(1: string name), //abool indexNews(1: NewsModel.News indexNews), //bNewsModel.News getNewsById(1: i32 newsId), //cmap getNewsMap(1: i32 newsType), list getNewsList(1: i32 newsType), // ”oneway”标识符表示client发出请求后不必等待回复(非阻塞)直接进行下面的操作, // ”oneway”方法的返回值必须是void oneway void zip() // d
}



说明:
a. 函数定义可以使用逗号或者分号标识结束
b. 参数可以是基本类型或者结构体,参数是只读的(const),不可以作为返回值!!!
c. 返回值可以是基本类型或者结构体
d. 返回值可以是void
注意,函数中参数列表的定义方式与struct完全一样
Service支持继承,一个service可使用extends关键字继承另一个service


三、  编译&产生代码
WINDOWS配置thrift开发环境
1.安装thrift:到thrift官网下载exe文件,下载地址:http://thrift.apache.org/download。然后将文件重命名为thrift.exe,拷贝到F:\thrift目录下(或者任何目录下),然后就可以在dos环境下使用了,如下:
F:\thrift>thrift -gen java D:\mywork\javaProject\thriftTest\test.thrift ,输出的java文件默认输出到当前目录下F:\thrift,也可以使用-o参数指定输出路径。

在Windows环境下进行编译时出现以下问题,如图:


原来是编码问题,最后统一thrift文件的编码为UTF-8就可以正常编译通过了。

四、编写Client与Service端
1.下载相关依赖包
a. libthrift.jar
b. slf4j-api.jar
c. slf4j-simple.jar

2.编写接口实现代码

package com.example.thrift.impl;import java.util.List;
import java.util.Map;import org.apache.thrift.TException;import com.example.thrift.model.News;
import com.example.thrift.service.DataSource;public class DataSourceHandler implements DataSource.Iface{@Overridepublic String helloWorld(String name) throws TException {// TODO Auto-generated method stubreturn "hello "+name+",welcom to thrift!";}@Overridepublic boolean indexNews(News indexNews) throws TException {// TODO Auto-generated method stubreturn false;}@Overridepublic News getNewsById(int newsId) throws TException {News news = new News();news.setId(1000);news.setAuthor("Ricky Feng");news.setContent("thrift demo");return news;}@Overridepublic Map getNewsMap(int newsType) throws TException {// TODO Auto-generated method stubreturn null;}@Overridepublic List getNewsList(int newsType) throws TException {// TODO Auto-generated method stubreturn null;}}


3.编写server代码

package com.example.thrift;import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;
import com.example.thrift.impl.DataSourceHandler;
import com.example.thrift.service.DataSource;public class HelloServer {public static final int SERVER_PORT = 8090;public static void main(String[] args) {startServer();}private static void startServer() {try {System.out.println("HelloServer TSimpleServer start ....");TProcessor tprocessor = new DataSource.Processor(new DataSourceHandler());// 简单的单线程服务模型,一般用于测试TServerSocket serverTransport = new TServerSocket(SERVER_PORT);TServer.Args tArgs = new TServer.Args(serverTransport);tArgs.processor(tprocessor);tArgs.protocolFactory(new TBinaryProtocol.Factory());TServer server = new TSimpleServer(tArgs);server.serve();} catch (TTransportException e) {e.printStackTrace();}}
}


4.编写client代码


package com.example.thrift;import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;import com.example.thrift.service.DataSource;public class HelloClient {public static final String SERVER_IP = "localhost";public static final int SERVER_PORT = 8090;public static final int TIMEOUT = 30000;public static void main(String[] args) {startClient();}private static void startClient() {TTransport transport = null;try {System.out.println("HelloClient start ....");transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT);// 协议要和服务端一致TProtocol protocol = new TBinaryProtocol(transport);// TProtocol protocol = new TCompactProtocol(transport);// TProtocol protocol = new TJSONProtocol(transport);DataSource.Client client = new DataSource.Client(protocol);transport.open();String result = client.helloWorld("Ricky");System.out.println("Thrify client result =: " + result);} catch (TTransportException e) {e.printStackTrace();} catch (TException e) {e.printStackTrace();} finally {if (null != transport) {transport.close();}}}
}


先运行HelloServer启动服务,然后运行HelloClient就可以看见控制台打印:

HelloClient start ....
Thrify client result =: hello Ricky,welcom to thrift!

说明客户端调用成功啦!



关于Thrift使用的详细示例可以参考Apache Thrift网站上的Tutorial,地址:http://thrift.apache.org/tutorial/java



最后附上示例代码下载地址:http://download.csdn.net/detail/fx_sky/7499361





推荐阅读
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 开发笔记:Python之路第一篇:初识Python
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Python之路第一篇:初识Python相关的知识,希望对你有一定的参考价值。Python简介& ... [详细]
  • Hadoop 源码学习笔记(4)Hdfs 数据读写流程分析
    Hdfs的数据模型在对读写流程进行分析之前,我们需要先对Hdfs的数据模型有一个简单的认知。数据模型如上图所示,在NameNode中有一个唯一的FSDirectory类负责维护文件 ... [详细]
  • 本文为转载,原连接:https:www.zhihu.comquestion40822826简单说一下吧做要解释这些要从netconf说起。netconf ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • 使用CocoaPods管理依赖库
    这篇内容将介绍Mac和iOS开发中必备的一个依赖库管理工具CocoaPods。在iOS开发中势必会用到一些第三方依赖库,比如大家都熟悉的ASIHttpRequest、AFNetwo ... [详细]
  • springboot dubbo框架中log4j与slf4jlog4j12日志冲突问题的解决方法
    在基于springboot开发项目中,使用dubbo的RPC框架进行业务拆分,出 ... [详细]
  • mapreduce原理_MapReduce原理及WordCount实践
    参考链接:https:www.cnblogs.comlaowangcp8961946.html一、MapReduce流程1.1Mapreduce整体流程: ... [详细]
author-avatar
阿莱沃_132
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有