【thirft 简介】
维基百科:
Thrift是一种接口描述语言和二进制通讯协议,[1]它被用来定义和创建跨语言的服务。[2]它被当作一个远程过程调用(RPC)框架来使用,是由Facebook为“大规模跨语言服务开发”而开发的。它通过一个代码生成引擎联合了一个软件栈,来创建不同程度的、无缝的跨平台高效服务,可以使用C#、C++(基于POSIX兼容系统[3])、Cappuccino、[4]Cocoa、Delphi、Erlang、Go、Haskell、Java、Node.js、OCaml、Perl、PHP、Python、Ruby和Smalltalk。[5]虽然它以前是由Facebook开发的,但它现在是Apache软件基金会的开源项目了。该实现被描述在2007年4月的一篇由Facebook发表的技术论文中,该论文现由Apache掌管
简单来说thrift就是Facebook 开发的一个语言中立、平台中立的RPC 框架。
mac 环境使用brew 安装:
brew install thrift
PRC
先简要说一下什么是RPC。
RPC,即Remote Procedure Call,意为远程过程调用,什么是远程过程调用?举个简单的例子:
假设你和兄弟住在同一个房间,你在外面时突然想起衣服忘洗了,于是打电话让兄弟把衣服洗了
在这个例子中你和兄弟就相当于两个应用A/B,你在外面就相当于两个不同的服务环境,洗衣服就相当于一个服务。
A 应用想调用B应用的服务,但因为不在同一个环境所以无法操作成功,就相当于你在外面不能洗衣服,而兄弟可以。于是你打电话给兄弟,让他帮你洗衣服,就是一次远程过程调用。
远程过程调用需要在A、B之间建立一个通信通道,就相当于你给兄弟打电话需要通讯信号,手机的那一套的东西,RPC 框架就是把那一套给你屏蔽了,就相当于你只需要买个手机、电话卡就行了。电话与电话之间怎么链接的你就不用管了。
Thrift 语言中立
thrift 通过一个中间语言IDL(接口定义语言)来定义RPC的数据类型和接口,以.thrift 结尾,然后可以根据需求编译成想要的文件。
比如创建一个服务Hello,创建文件Hello.thrift,代码如下:
namespace java service.demo
service Hello{
string helloString(1:string para)
}
然后通过命令生成java 代码:
thrift -r -gen java Hello.thrift
生成的代码中不但包含目标语言的接口定义、方法、数据类型,还包含有RPC协议层和传输层的实现代码:
/**
* Autogenerated by Thrift Compiler (0.13.0)
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
* @generated
*/
package com.thrift;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-02-20")
public class Hello {
public interface Iface {
public String helloString(String para) throws org.apache.thrift.TException;
}
public interface AsyncIface {
public void helloString(String para, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws org.apache.thrift.TException;
}
public static class Client extends org.apache.thrift.TServiceClient implements Iface {
public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
public Factory() {}
public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
return new Client(prot);
}
public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
return new Client(iprot, oprot);
}
}
public Client(org.apache.thrift.protocol.TProtocol prot)
{
super(prot, prot);
}
public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
super(iprot, oprot);
}
public String helloString(String para) throws org.apache.thrift.TException
{
send_helloString(para);
return recv_helloString();
}
public void send_helloString(String para) throws org.apache.thrift.TException
{
helloString_args args = new helloString_args();
args.setPara(para);
sendBase("helloString", args);
}
public String recv_helloString() throws org.apache.thrift.TException
{
helloString_result result = new helloString_result();
receiveBase(result, "helloString");
if (result.isSetSuccess()) {
return result.success;
}
throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "helloString failed: unknown result");
}
}
...
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AgIG8Rbh-1582208172872)(http://note.youdao.com/yws/res/10552/54EC0AF180E64D34B7D2262F2376D39A)]
当然也可以生产c++ 或者其他的开发语言看自己的需求。
Thirft demo,该博客需要把thrift maven版本升级到0.12.0,不然会找不到annotation 类的错误
Thrift 协议栈
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dc3Kx6sE-1582208172874)(http://note.youdao.com/yws/res/10559/A8D89B272593441BBDA9F808FEA27A77)]
Thrift是一种c/s的架构体系。Server主要任务是高效的接受客户端请求,并将请求转发给Processor处理。
- 最上层是用户自行实现的业务逻辑代码;
- Processor是由thrift编译器自动生成的代码,它封装了从输入数据流中读数据和向数据流中写数据的操作,它的主要工作是:从连接中读取数据,把处理交给用户实现impl,最后把结果写到连接上。
- TProtocol(协议层),定义数据传输格式,例如:
- TBinaryProtocol:二进制格式;
- TCompactProtocol:压缩格式;
- TJSONProtocol:JSON格式;
- TSimpleJSONProtocol:提供JSON只写协议, 生成的文件很容易通过脚本语言解析;
- TDebugProtocol:使用易懂的可读的文本格式,以便于debug
- TTransport(传输层),定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等)被用作运行时库。
- TSocket:阻塞式socker;
- TFramedTransport:以frame为单位进行传输,非阻塞式服务中使用;
- TFileTransport:以文件形式进行传输;
- TMemoryTransport:将内存用于I/O,java实现时内部实际使用了简单的ByteArrayOutputStream;
- TZlibTransport:使用zlib进行压缩, 与其他传输方式联合使用,当前无java实现
- 底层IO负责实际的数据传输,包括socket、文件和压缩数据流等。
- Thrift支持的服务模型
- TSimpleServer:简单的单线程服务模型,常用于测试;
- TThreadPoolServer:多线程服务模型,使用标准的阻塞式IO;
- TNonblockingServer:多线程服务模型,使用非阻塞式IO(需使用TFramedTransport数据传输方式);
【Thrift 与Dubbo 的区别】
转载自参考博客:https://blog.youkuaiyun.com/JustKian/article/details/102495650
透明化服务调用
Thrift:通过IDL(接口定义语言)实现,Thrift是支持跨语言的,而要实现跨语言机制,就需要一种中间语言来完成,那就是IDL。首先定义好了IDL之后(即定义好了一个service),由于server和Client都需要持有这个与之语言相对应的服务接口,那就需要thrift来将IDL编译成与之语言相对应的接口类,比如server端是java,client端是C#,则server端需要编译成java类,client编译成C#类。然后server端负责接口的具体实现,client只需要持有这个对象接口,进行调用即可,然后通过网络通信传给server。server负责解析client传递过来的数据,由于服务对象接口统一为IDL(thrift格式),所以统一了解析形式,只和本地的开发语言有关。
Dubbo:通过java反射和动态代理实现这一功能,由于只支持Java,所以Client和Server端开发语言机制一样,所以它们能够通过spring框架进行依赖,server端一般将对象方法接口注册发布到Zookeper中,然后Client可以直接从Zookeper中获取server端发布的对象方法接口,这样Client可以通过Spring进行自动装配获得server端发布的对象方法服务接口。
网络通信
thrift 参考上文
Thrift实际上是实现了C/S模式,通过代码生成工具将thrift文生成服务器端和客户端代码(可以为不同语言),从而实现服务端和客户端跨语言的支持。用户在Thirft文件中声明自己的服务,这些服务经过编译后会生成相应语言的代码文件,然后客户端调用服务,服务器端提服务便可以了。
dubbo网络通讯层主要实现了以下功能:
- 多种网络通讯框架的抽象封装(netty,mina,grizzly)
- 每个客户端主机和服务端保存单个长链接通信
- 异步调用转同步
- tcp链接的心跳和自动重连
- 基于header头通讯协议,请求的编解码器
dubbo的网络通信基于NIO框架,一般基于事件的NIO网络框架都涉及到 channel , channelHandle核心概念,网络数据buffer, 网络数据编解码器,dubbo为了能够适配多种NIO框架,将以上概念全部又抽象了一层接口。如果有netty开发经验或者了解netty helloworld demo程序对于理解这个章节非常有帮助。
参考链接:
https://www.jianshu.com/p/1e0c8c08e89d
https://www.jianshu.com/p/1a1404ce2201
https://blog.youkuaiyun.com/qq418517226/article/details/51906357
序列化
thrift只支持对thrift协议描述的IDL进行序列化,包含如下几种序列化格式:
- TBinaryProtocol:二进制格式;
- TCompactProtocol:压缩格式;
- TJSONProtocol:JSON格式;
- TSimpleJSONProtocol:提供JSON只写协议, 生成的文件很容易通过脚本语言解析;
- TDebugProtocol:使用易懂的可读的文本格式,以便于debug
dubbo支持各种协议的序列化(实际上,dubbo没有IDL这一机制,因为实际上他就是通过java服务对象接口进行交互的)
例如他也可支持thrift协议,只需要thrift将IDL转换为一个java服务对象接口,那么dubbo就可以使用了
【附录】
- 基本类型:
- 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
- 结构体类型:
- struct:定义公共的对象,类似于 C 语言中的结构体定义,在 Java 中是一个 JavaBean
- 容器类型:
- list:对应 Java 的 ArrayList
- set:对应 Java 的 HashSet
- map:对应 Java 的 HashMap
- 异常类型:
- exception:对应 Java 的 Exception
- 服务类型:
- service:对应服务的类