Java学习笔记(十)——Thrift入门及一些基础知识介绍

栏目: 服务器 · 发布时间: 7年前

内容简介:公司跨项目协作,一些部门服务框架底层封装了thrift提供服务,于是对thrift简单做了一些了解。Facebook公布的一款开源跨语言的RPC框架。什么是RPC框架呢?RPC全称为Remote Procedure Call,意为远程过程调用。

公司跨项目协作,一些部门服务框架底层封装了thrift提供服务,于是对thrift简单做了一些了解。

关于thrift

Facebook公布的一款开源跨语言的RPC框架。

什么是RPC框架呢?RPC全称为Remote Procedure Call,意为远程过程调用。

其实简单来说有两个系统,一个系统想调用另一个系统,但两个系统不在同一个进程,需要通过网络来传输,而网络传输需要涉及Socket,序列化反序列化,网络I/O等一系列的事项,牛掰的 程序员 将这一过程封装起来做成了一个框架,就是RPC框架,而thrift是其中一种。

thrift通过一个中间语言IDL(接口定义语言)来定义RPC的数据类型和接口,这些内容写在以.thrift结尾的文件中,然后通过特殊的编译器来生成不同语言的代码,以满足不同需要的开发者,比如 java 开发者,就可以生成java代码,c++ 开发者可以生成c++ 代码,生成的代码中不但包含目标语言的接口定义,方法,数据类型,还包含有RPC协议层和传输层的实现代码。

Java学习笔记(十)——Thrift入门及一些基础知识介绍

安装thrift

安装前的小插曲

一开始打算用 Homebrew 装的,想象 Homebrew 好久没更新了,首先更新了一把 brew update ,结果mac居然报了下面的错误:

invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at:

google了一下发现是因为macOS本身升级造成的,需要安装下Command line tools,调用下命令即可,但是非常慢,装了几十分钟。

xcode-select --install

Java学习笔记(十)——Thrift入门及一些基础知识介绍

当我解决了这个问题之后,发现用brew装只能装最新版本的,但由于提供方目前使用的是 0.9.3 的版本,为了保证一致,所以打算跟他们一样,所以放弃了使用brew使用。

mac下正式安装

首先到 官网 下载对应版本的安装包,选择对应的版本就可以了。

Java学习笔记(十)——Thrift入门及一些基础知识介绍

下载下来之后,解压后进入到目录进行如下操作:

#Step 1
./configure --prefix=/usr/local/ --with-boost=/usr/local --with-libevent=/usr/local --without-ruby --without-perl --without-php --without-nodejs

#Step 2
make

#Step 3
make install

在执行第一步的时候发现报错了,错误如下:

configure: error: Bison version 2.5 or higher must be installed on the system!

原因是mac上预安装bison版本过低,需要升级下bison,直接通过homebrew安装即可:

brew install bison

安装后还需要替换一下路径,默认安装的路径是在:

/usr/local/opt/bison/bin/bison

而系统自带时的路径是在:

/Library/Developer/CommandLineTools/usr/bin/

将原来的bison重命名下,然后将新的bison复制进去:

mv bison bison_copy
cp /usr/local/opt/bison/bin/bison /Library/Developer/CommandLineTools/usr/bin/

这样重复上面的步骤即可,安装后可以查看下版本,如果正常展示就说明安装成功了:

thrift -version

数据类型及关键字

基本类型

thrift不支持无符号的类型,无符号类型可以简单理解为不能表示负数,只能表示正数的类型,像java的基本数据类型都是有符号的类型。

byte:有符号字节
i32:32位有符号整数,此外还有i16,i64
double:64位浮点数
string:二进制字符串
bool 布尔值 true或false

结构体类型(struct)

类似于 c语言 的结构体定义,在java中会被转化为javabean类。

struct DemoModel {
  1: i32 id;
  2: string name;
  3: double number;
  4: bool flag;
}

服务类型(service)

service:对应服务的接口,内部可定义各种方法,相当于java中创建interface一样,创建的service经过代码生成命令会生成客户端,服务端的框架代码。

service DemoService{
  string demoString(1:string s);
  i32 demoInt(1:i32 i);
  bool demoBoolean(1:bool b);
  void demoVoid();
  string demoNull();
}

异常类型(Exception)

exception RequestException {

  1:i32 code;

  2:string msg;

}

容器类型

集合中的元素可以是除了service之外的任意类型。

list<T>:有序列表,元素可重复

set<T>:无需集合,元素不可重复

map<K,V>:键值对集合

枚举类型

enum StatusEnum{

  Success,

  Error

}

命名空间(namespace)

可以理解成java中的packet,用于避免一些代码冲突,每种语言都有属于自己的命名空间的方式,比如java语言,就可以使用java语言的格式。

namespace java com.demo.project

其他常用的

required string name1: 必选参数
optional string name2: 可选参数
const string strDemo = "demo": 定义常量
include "demo.thrift" 引入文件

Thrift支持的传输协议

Thrift支持多种传输协议,我们可以根据自己的需要来选择合适的类型,总体上来说,分为文本传输和二进制传输,由于二进制传输在传输速率和节省带宽上有优势,所以大部分情况下使用二进制传输是比较好的选择。

TBinaryProtocol:使用二进制编码格式传输,是thrift的默认传输协议

TCompactProtocol:使用压缩格式传输

TJSONProtocol :使用JSON格式传输

TDebugProtocol : 使用易懂可读的文本格式进行传输,以便于debug

TSimpleJSONProtocol : 提供JSON只写的协议,适用于通过脚本语言解析

Thrift支持的传输模式

Thrift封装了一层传输层来支持底层的网络通信,在Thrift中称为Transport,不仅提供open,close,flush等方法,还有一些read/write方法。

TSocket:阻塞式IO的Transport实现,用在客户端.

TServerSocket:非阻塞式Socket,用于服务器端,用于监听TSocket.

TNonblockingSocket:非阻塞式IO的实现

TMemoryInputTransport: 封装了一个字节数组byte[]来做输入流的封装

TFramedTransport: 同样使用非阻塞方式,按块的大小进行传输,输入流封装了TMemoryInputTransport 

Thrift支持的服务模型

TSimpleServer

这种工作模式只有一个线程,循环监听传过来的请求并对其进行处理,处理完才能接受下一个请求,是一种阻塞式IO的实现,因为效率比较低,实际线上环境一般用不到.一般用于开发时候演示工作流程时使用。

TNonblockingServer

这种模式与TsimpleServer最大的区别就是使用NIO,也就是非阻塞是IO的方式实现IO的多路复用,它可以同时监听多个socket的变化,但因为业务处理上还是单线程模式,所以在一些业务处理比较复杂耗时的时候效率还是不高,因为多个请求任务依然需要排队一个一个进行处理。

TThreadPoolServer

这种模式引入了线程池,主线程只负责accept,即监听Socket,当有新的请求(客户端Socket)来时,就会在线程池里起一个线程来处理业务逻辑,这样在并发量比较大的时候(但不超过线程池的数量)每个请求都能及时被处理,效率比较高,但一旦并发量很大的时候(超过线程池数量),后面来的请求也只能排队等待。

TThreadedSelectorServer

这是一种多线程半同步半异步的服务模型,是Thrift提供的最复杂最高级的服务模型,内部有一个专门负责处理监听Socket的线程,有多个专门处理业务中网络IO的线程,有一个专门负责决定将新Socket连接分配给哪一个线程处理的起负载均衡作用的线程,还有一个工作线程池.这种模型既可以响应大量并发连接的请求又可以快速对网络IO进行读写,能适配很多场景,因此是一种使用比较高频的服务模。

java实现

通过一个小demo来了解下thrift和具体的编码实现。

首先我们创建个thrift文件,简单定义了一个方法:

namespace java service.demo
service Hello{
    string helloString(1:string para)
}

创建好 Hello.thrift 后通过终端生成java的代码:

thrift -r -gen java Hello.thrift

发现在当前目录下多了一个 gen-java 的目录,里面的有一个 Hello.java 的文件.这个java文件包含Hello服务的接口定义 Hello.Iface ,以及服务调用的底层通信细节,包括客户端的调用逻辑 Hello.Client 以及服务端的处理逻辑 Hello.Processor

接着可以引入jar包,然后将生成的代码复制到项目中:

<dependency>
     <groupId>org.apache.thrift</groupId>
     <artifactId>libthrift</artifactId>
     <version>0.9.3</version>
</dependency>

然后创建HelloServiceImpl实现Hello.Iface接口:

package service.demo;
import org.apache.thrift.TException;

public class HelloServiceImpl implements Hello.Iface {
    public String helloString(String para) throws TException {
        return "result:"+para;
    }
}

接着创建服务端实现代码HelloServiceServer,把HelloServiceImpl作为一个具体的处理器传递给Thrift服务器:

package service.demo;
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;


public class HelloServiceServer {
    public static void main(String[] args) {
        try {
            System.out.println("服务端开启....");
            TProcessor tprocessor = new Hello.Processor<Hello.Iface>(new HelloServiceImpl());
            // 简单的单线程服务模型
            TServerSocket serverTransport = new TServerSocket(9898);
            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();
        }
    }
}

最后创建客户端实现代码HelloServiceClient,调用Hello.client访问服务端的逻辑实现

package service.demo;

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;


public class HelloServiceClient {

    public static void main(String[] args) {
        System.out.println("客户端启动....");
        TTransport transport = null;
        try {
            transport = new TSocket("localhost", 9898, 30000);
            // 协议要和服务端一致
            TProtocol protocol = new TBinaryProtocol(transport);
            Hello.Client client = new Hello.Client(protocol);
            transport.open();
            String result = client.helloString("哈哈");
            System.out.println(result);
        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            if (null != transport) {
                transport.close();
            }
        }
    }
}

启动服务端和客户端就能看到效果啦。

总结

简单了解了thrift之后就开始代码变现了,有空还是需要深入了解下的。

另外看到一篇thrift与http性能对比的文章( 小测thrift和http在node.js中的性能对比 ),发现thrift性能还是可以的,毕竟现在大多情况下我们的服务还是使用http通过json传输的。如果对于性能有高要求的业务场景,可以考虑thrift的。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Concepts, Techniques, and Models of Computer Programming

Concepts, Techniques, and Models of Computer Programming

Peter Van Roy、Seif Haridi / The MIT Press / 2004-2-20 / USD 78.00

This innovative text presents computer programming as a unified discipline in a way that is both practical and scientifically sound. The book focuses on techniques of lasting value and explains them p......一起来看看 《Concepts, Techniques, and Models of Computer Programming》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具