精通并发与 Netty (一)常用的 rpc 框架 (2)

Thrift 是一个典型的 CS 结构,客户端和服务端可以使用不同的语言开发,既然客户端和服务端能使用不同的语言开发,那么一定有一种中间语言来关联服务端和客户端,这就是 IDL(Interface Description Language)。

Thrift 如何实现多语言之间的通信?

数据传输使用 socket (多种语言均支持),数据再以特定的格式(String 等)发送,接收方语言进行解析。

如何使用?

定义 thrift 的文件,由 thrift 文件(IDL) 生成双方语言的接口,model,在生成的 model 以及接口中会有解码编码的代码。

Thrift 中的服务

Thrift 定义服务相当于 Java 中创建 Interface 一样,创建的 service 经过代码生成命令之后就会生成客户端和服务端的框架代码,定义形式如下:

service HelloWorldService{ //service 中定义的函数,相当于 java interface 中定义的方法 string doAction(1:string name, 2:i32 age); }

.thrift 文件的定义

// java 中的包名 namespace jave thrift.generate // 定义别名 typedef i16 short typedef i32 int typedef i64 long typedef bool boolean typedef string String struct Person{ 1: optional String username, 2: optional int age, 3: optional boolean married } exception DataException{ 1: optional String message, 2: optional String callStack, 3: optional String date } service PersonService{ Person getPersonByName(1: required String username) throws (1: DataException dataException), void savePerson(1:requried Person person) throws (1:DataException dataException) }

编译 thrift 文件

thrift --gen java src/thrift/data.thrift

生成的文件

精通并发与 Netty (一)常用的 rpc 框架

Person.java 里面包含了编解码的方法,PersonService 里面包含了 getPersonByName 和 savePerson 的方法。

测试方法:

服务端服务的具体实现方法

public class PersonServiceImpl implements PersonService.Iface{ @Override public Person getPersonByName(String username) throws DataException,TException{ Person p = new Person(); p.setUserName("paul"); p.setAge(25); p.setMarried(true); return p; } @Override public void savePerson(Person person) throws DataException,TException{ System.out.println(person.getUserName()); } }

Thrift 的服务端:

public class ThriftServer{ public static void main(String[] args){ //非阻塞的 socket server TNonblockingServerSocket socket = new TNonblockingServerSocket(8899); // 高可用的 server THsHaServer.Args arg = new THsHaServer.Args(socket).minWorkerThreads(2).maxWorkerThreads(4); PersonService.Processor<PersonServiceImpl> processor = new PersonService.Processor<>(new PersonServiceImpl()); arg.protocolFactory(new TCompactPrococol.Factory()); arg.transportFactory(new TFramedTransport.Facotry()); arg.processorFactory(new TProcessorFactory(processor)); TServer server = new THsHaServer(arg); System.out.println("Thrift Server Started"); //死循环 server.serve(); } }

Thrift 的客户端:

public class ThriftClient{ publiuc static void main(String[] args){ TTransport transport = new TFramedTransport(new TSocket ("localhost",8899),600); TProcotol procotol = new TComapctProcotol(transport); PersonService.Client client = new PersonService.Client(procotol); try{ //打开 socket transport.open(); //好像调用本地方法一样 Person person = client.getPersonByName("paul"); System.out.println(person.getAge()); }catch(Exception ex){ throw ex; }finally{ transport.close(); } } }

Thrift 的架构:

Thrift 的传输格式,协议:

TBinaryProtocol-二进制格式

TCompactProtocol-压缩格式

TJSONProtocol-JSON 格式

TSimpleJSONProtocol-提供 JSON 只写协议,生成的文件很容易通过脚本语言解析。很少使用,缺少元数据信息,接收方不能读取出来。

TDebugProtocol-使用易懂的可读的文本格式,以便于 debug。

精通并发与 Netty (一)常用的 rpc 框架

Thrift 数据传输方式,transport:

TSocket-阻塞式 socket。

TFramedTransport-以 frame 为单位进行传输,非阻塞式服务中使用。

TFileTransport-以文件形式进行传输。

TMemoryTransport-将内存用于 I/O,Java 实现时内部实际使用了简单的 ByteArrayOutputStream。

支持的服务模型,server:

TSimpleServer-简单的单线程服务模型,常用于测试。

TThreadPoolServer-多线程服务模型,标准的阻塞式 IO。

TNonboockingServer-多线程服务模型,使用非阻塞式 IO(需要使用 TFramedTransport 数据传输方式)。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfsxy.html