热门标签 | 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





推荐阅读
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 本指南介绍了如何在ASP.NET Web应用程序中利用C#和JavaScript实现基于指纹识别的登录系统。通过集成指纹识别技术,用户无需输入传统的登录ID即可完成身份验证,从而提升用户体验和安全性。我们将详细探讨如何配置和部署这一功能,确保系统的稳定性和可靠性。 ... [详细]
  • Java能否直接通过HTTP将字节流绕过HEAP写入SD卡? ... [详细]
  • 本文详细介绍了如何在Java Web服务器上部署音视频服务,并提供了完整的验证流程。以AnyChat为例,这是一款跨平台的音视频解决方案,广泛应用于需要实时音视频交互的项目中。通过具体的部署步骤和测试方法,确保了音视频服务的稳定性和可靠性。 ... [详细]
  • 本文主要探讨了Java中处理ActionEvent事件的接口,以及一些常见的编程问题和解决方案,包括方法重载、成员变量访问、镜片质量检测等。 ... [详细]
  • 原文网址:https:www.cnblogs.comysoceanp7476379.html目录1、AOP什么?2、需求3、解决办法1:使用静态代理4 ... [详细]
  • 如何使用 `org.eclipse.rdf4j.query.impl.MapBindingSet.getValue()` 方法及其代码示例详解 ... [详细]
  • 在C#编程中,枚举是一种非常实用的数据类型,能够有效提高代码的可读性和维护性。本文详细探讨了枚举在实际开发中的多种应用场景,包括状态管理、配置选项和数据分类等,并通过具体示例展示了如何高效地使用枚举来简化代码逻辑。此外,还介绍了枚举的一些高级用法,如自定义属性和扩展方法,以进一步增强其功能和灵活性。 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
  • 在处理 XML 数据时,如果需要解析 `` 标签的内容,可以采用 Pull 解析方法。Pull 解析是一种高效的 XML 解析方式,适用于流式数据处理。具体实现中,可以通过 Java 的 `XmlPullParser` 或其他类似的库来逐步读取和解析 XML 文档中的 `` 元素。这样不仅能够提高解析效率,还能减少内存占用。本文将详细介绍如何使用 Pull 解析方法来提取 `` 标签的内容,并提供一个示例代码,帮助开发者快速解决问题。 ... [详细]
  • 在Java Web服务开发中,Apache CXF 和 Axis2 是两个广泛使用的框架。CXF 由于其与 Spring 框架的无缝集成能力,以及更简便的部署方式,成为了许多开发者的首选。本文将详细介绍如何使用 CXF 框架进行 Web 服务的开发,包括环境搭建、服务发布和客户端调用等关键步骤,为开发者提供一个全面的实践指南。 ... [详细]
  • 本文介绍了如何利用 Delphi 中的 IdTCPServer 和 IdTCPClient 控件实现高效的文件传输。这些控件在默认情况下采用阻塞模式,并且服务器端已经集成了多线程处理,能够支持任意大小的文件传输,无需担心数据包大小的限制。与传统的 ClientSocket 相比,Indy 控件提供了更为简洁和可靠的解决方案,特别适用于开发高性能的网络文件传输应用程序。 ... [详细]
  • 深入解析C#中app.config文件的配置与修改方法
    在C#开发过程中,经常需要对系统的配置文件进行读写操作,如系统初始化参数的修改或运行时参数的更新。本文将详细介绍如何在C#中正确配置和修改app.config文件,包括其结构、常见用法以及最佳实践。此外,还将探讨exe.config文件的生成机制及其在不同环境下的应用,帮助开发者更好地管理和维护应用程序的配置信息。 ... [详细]
  • 如何精通编程语言:全面指南与实用技巧
    如何精通编程语言:全面指南与实用技巧 ... [详细]
  • 当前,众多初创企业对全栈工程师的需求日益增长,但市场中却存在大量所谓的“伪全栈工程师”,尤其是那些仅掌握了Node.js技能的前端开发人员。本文旨在深入探讨全栈工程师在现代技术生态中的真实角色与价值,澄清对这一角色的误解,并强调真正的全栈工程师应具备全面的技术栈和综合解决问题的能力。 ... [详细]
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社区 版权所有