但是我对它的使用还不是很了解,因此找了一篇文章想上手做一些demo,参考Thrift 初认识 & Thrift 和Dubbo 的区别_dubbo和thrift的区别-CSDN博客
brew install thrift 在 mac上就可以安装,很无敌,但是公司里好像不是这么干的
thrift通过一个中间语言IDL(接口定义语言)来定义RPC的数据类型和接口,这些内容写在以.thrift结尾的文件中,然后通过特殊的编译器来生成不同语言的代码,以满足不同需要的开发者。比如java开发者,就可以生成java代码,c++开发者可以生成c++代码,生成的代码中不但包含目标语言的接口定义、方法、数据类型,还包含有RPC协议层和传输层的实现代码。
比如代码如下:
namespace java service.demo
service Hello{
string helloString(1:string para)
}
thrift -r -gen java Hello.thrift
发现在当前目录下多了一个gen-java的目录,里面的有一个Hello.java的文件。这个java文件包含Hello服务的接口定义Hello.Iface,以及服务调用的底层通信细节,包括客户端的调用逻辑Hello.Client以及服务端的处理逻辑Hello.Processor。
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.19.0</version>
</dependency>
package com.jxz.thriftdemo;
import com.jxz.thriftdemo.idl.Hello;
import org.apache.thrift.TException;
/**
* @Author jiangxuzhao
* @Description
* @Date 2024/1/14
*/
public class HelloServiceImpl implements Hello.Iface{
@Override
public String helloString(String para) throws TException {
return "result = " + para;
}
}
这里在编译的时候可能会找不到@javax.annotation.Generated,这是因为本地jdk版本较高导致的,可以直接删掉这个注解,它仅代表这个文件是自动生成的
package com.jxz.thriftdemo.server;
import com.jxz.thriftdemo.idl.Hello;
import com.jxz.thriftdemo.impl.HelloServiceImpl;
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;
/**
* @Author jiangxuzhao
* @Description
* @Date 2024/1/14
*/
public class HelloServiceServer {
public static void main(String[] args) {
try {
System.out.println("服务端开启...");
// 1. 创建TProcessor,传入处理器
TProcessor tprocessor = new Hello.Processor<>(new HelloServiceImpl());
// 2. 创建Tprotocol,这里采用二进制格式
TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory();
// 3. 创建TserverTransport,监听端口
TServerSocket serverTransport = new TServerSocket(8083);
TServer.Args tArgs = new TServer.Args(serverTransport);
tArgs.processor(tprocessor);
tArgs.protocolFactory(factory);
// 4. 创建Tserver,传入需要的参数,server将以上内容集成在一起
TSimpleServer server = new TSimpleServer(tArgs);
// 5. 启动server
server.serve();
} catch (TTransportException e) {
throw new RuntimeException(e);
}
}
}
package com.jxz.thriftdemo.client;
import com.jxz.thriftdemo.idl.Hello;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
/**
* @Author jiangxuzhao
* @Description
* @Date 2024/1/14
*/
public class HelloServiceClient {
public static void main(String[] args) {
System.out.println("客户端启动...");
TTransport tTransport = null;
try {
// 1. 创建TTransport
tTransport = new TSocket("127.0.0.1", 8083, 5000);
// 2. 创建Tprotocol,这里采用二进制格式
TBinaryProtocol tProtocol = new TBinaryProtocol(tTransport);
// 3. 创建TProcessor,由于这里需要用到具体的方法,因此不能用泛型
Hello.Client client = new Hello.Client(tProtocol);
// 4. 打开传输层
tTransport.open();
// 5. 启动client
String result = null;
result = client.helloString("hello world");
System.out.println(result);
} catch (TTransportException e) {
throw new RuntimeException(e);
} catch (TException e) {
throw new RuntimeException(e);
} finally {
// 6. 最后关闭传输流
if (null != tTransport) {
tTransport.close();
}
}
}
}
先启动服务端,然后启动客户端,最后客户端输出如下:
客户端启动...
result = hello world
可以明显地看出来,客户端RPC调用了服务端的方法,服务器里面的具体处理器为HelloServiceImpl对象
Thrift是一种c/s的架构体系。Server主要任务是高效的接受客户端请求,并将请求转发给Processor处理。
最上层是用户自行实现的业务逻辑代码;
Processor是由thrift编译器自动生成的代码,它封装了从输入数据流中读数据和向数据流中写数据的操作,它的主要工作是:从连接中读取数据,把处理交给用户实现impl,最后把结果写到连接上。
TProtocol(协议层),用于数据类型解析的,将结构化数据转化为字节流给TTransport进行传输,例如:
TTransport(传输层),定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等)被用作运行时库
底层IO负责实际的数据传输,包括socket、文件和压缩数据流等。
Thrift支持的服务模型
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网络通讯层主要实现了以下功能:
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.csdn.net/qq418517226/article/details/51906357
thrift只支持对thrift协议描述的IDL进行序列化,包含如下几种序列化格式:
dubbo支持各种协议的序列化,例如Hession,Jdk(实际上,dubbo没有IDL这一机制,因为实际上他就是通过java服务对象接口进行交互的)
例如他也可支持thrift协议,只需要thrift将IDL转换为一个java服务对象接口,那么dubbo就可以使用了