文档章节

Thrift原理学习-服务端

pointerException
 pointerException
发布于 2017/03/21 14:18
字数 1142
阅读 217
收藏 0

前言
    thrift是我所在公司使用的一款广泛的RPC框架,为了在之后的使用过程中,能够在遇到问题能够快速响应,解决。对了解其原理是很有必要的。今天先从服务端代码逻辑学起。 服务端实例 使用实例:开始之前首先看一个服务端使用过程中的一个例子:

namespace java com.wolfcoder.thrift
service Hello{
 string helloString(1:string para)
}
...
TProcessor tprocessor = new Hello.Processor<Hello.Iface>(new HelloWorldServiceImpl());//1
TServerSocket serverTransport = new TServerSocket(SERVER_PORT);//2
TServer.Args tArgs = new TServer.Args(serverTransport);//3
tArgs.processor(tprocessor);//4
tArgs.protocolFactory(new TBinaryProtocol.Factory());//5
TServer server = new TSimpleServer(tArgs);//6
server.serve();//7
...

1这段代码的目的就是注册该接口的方法列表。看下面的代码:

public Processor(I iface) {
  super(iface, getProcessMap(new HashMap<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>>()));
}
private static <I extends Iface> Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> getProcessMap(Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> processMap) {
  processMap.put("helloString", new helloString());
  return processMap;
}

getProcessMap方法体中已经生成了将所有的方法列表放置到map中的逻辑,最后会调用父类的构造方法,完成一个接口的注册。注册的内容包括:接口的具体实现类、方法列表。 2~5完成了服务端参数的包装。不细说。 6创建一个服务端实例,7开启一个服务线程接收服务。

public void serve() {
  stopped_ = false;
  try {
    serverTransport_.listen();
  } catch (TTransportException ttx) {
    LOGGER.error("Error occurred during listening.", ttx);
    return;
  }
  setServing(true);
  while (!stopped_) {
    try {
      client = serverTransport_.accept();
      if (client != null) {
        processor = processorFactory_.getProcessor(client);
        inputTransport = inputTransportFactory_.getTransport(client);
        outputTransport = outputTransportFactory_.getTransport(client);
        inputProtocol = inputProtocolFactory_.getProtocol(inputTransport);
        outputProtocol = outputProtocolFactory_.getProtocol(outputTransport);
        while (processor.process(inputProtocol, outputProtocol)) {}
      }
    } catch (TTransportException ttx) {
      // Client died, just move on
    } catch (TException tx) {
      if (!stopped_) {
        LOGGER.error("Thrift error occurred during processing of message.", tx);
      }
    } catch (Exception x) {
      if (!stopped_) {
        LOGGER.error("Error occurred during processing of message.", x);
      }
    }
  setServing(false);
}

serverTransport_:实际上就是我们在创建服务端实例时传入的参数,用来做socket通信。serverTransport_.listen():完成端口的监听。 下面会进入一个循环,在stoped_=false之前,都会进行判断服务。 serverTransport_.accept():阻塞接收客户端的连接。 processorFactory_.getProcessor(client):获取服务端配置的处理器。该处理器完成方法调用逻辑的封装。 具体的方法调用由Processor层来描述的。TProcessor只有一个方法process。

public boolean process(TProtocol in, TProtocol out) throws TException {
  TMessage msg = in.readMessageBegin();
  ProcessFunction fn = processMap.get(msg.name);
  fn.process(msg.seqid, in, out, iface);
  return true;
}

具体的方法执行流程中只需要关联两个协议层的对象,因为协议层对象包含了调用方调用信息的所有封装,同时协议层具备对结果封装的能力,所以在此只需要调用方和结果的封装对象即可。 in.readMessageBegin():读取调用方的请求头,包含的信息有:调用类型、方法名、请求号。 processMap.get(msg.name):在1中我们之后,在服务端代码执行最初会进行了一步注册过程,其中方法列表就保存在processMap中。key:方法名。value:方法描述对象(由thrift工具自动生成) ProcessFunction:对一个方法的描述,thrift工具生成一个方法对象的时候都会继承自该类。 方法的执行会委托给ProcessFunction#process来执行。

public final void process(int seqid, TProtocol iprot, TProtocol oprot, I iface) throws TException {
  T args = getEmptyArgsInstance();
  try {
    args.read(iprot);
  } catch (TProtocolException e) {
    iprot.readMessageEnd();
    TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage());
    oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid));
    x.write(oprot);
    oprot.writeMessageEnd();
    oprot.getTransport().flush();
    return;
  }
  iprot.readMessageEnd();
  TBase result = getResult(iface, args);
  oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.REPLY, seqid));
  result.write(oprot);
  oprot.writeMessageEnd();
  oprot.getTransport().flush();
}

getEmptyArgsInstance():该方法的具体实现是由thrift工具为我们生成的,返回了对方法参数的描述,类型名称为:xxx_args args.read(iport):参数数据的read操作采用委托的方式移交给xxx_args类的成员变量schemes来完成的,包含两类schemes:StandardScheme、TupleScheme,同样thrift为我们生成了以上两个接口的实例。命名规则是methodname_argsStandardScheme。 getResult():该方法的方法信息是由thrfit来生成的。下面是生成的方法模板:

protected helloString_result getResult(I iface, helloString_args args) throws org.apache.thrift.TException {
  helloString_result result = new helloString_result();
  result.success = iface.helloString(args.para);
  return result;
}

逻辑一目了然,就是创建一个method_result对象,用于对方法执行结果封装,然后调用一下方法。最后返回结果就ok了。 之后的过程就是写回结果信息给客户端。 当一次远程调用完成之后,就会继续进入下一次等待,等待客户端的调用请求。直到stoped=true就会停止。 注:文中涉及到多个由thrift根据我们的IDL声明来生成的方法或者类,如果不了解可能会有点迷糊。下篇笔记将了解一下所有的生成方法和类的作用。Thrift学习-生成文件源码分析

© 著作权归作者所有

pointerException
粉丝 6
博文 37
码字总数 32317
作品 0
西安
私信 提问
Thirft框架介绍

1、前言 Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目。Thrift通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和数据类型,然后通过一个编...

nothingfinal
2014/05/20
0
0
Thrift总结(二)创建RPC服务

  前面介绍了thrift 基础的东西,怎么写thrift 语法规范编写脚本,如何生成相关的语言的接口。不清楚的可以看这个《Thrift总结(一)介绍》。做好之前的准备工作以后,下面就开始如何用Thrif...

章为忠
2017/07/02
0
0
使用Nginx代理thrift NIO实现SSL链路加密

1 目标说明 1.1 调研目的 本次调研主要为了解决两个问题: thrift提供的SSL API只支持BIO(阻塞式IO),而我们使用的是NIO API,希望能在不改变IO模型的前提下对链路进行加密; 未来系统可能...

囚兔
2016/06/22
3.2K
11
MyThrift V0.3 增加注册中心实现服务注册和发现

本次更新主要是基于0.2的基础上增加了服务注册中心,基于ZooKeeper. 具体细节: 1) Server端 继承thrift的TThreadedSelectorServer类,覆盖setServing方法,使得thrift服务器端口处于监听状态...

强子1985
2016/10/30
2.3K
10
java程序员从入门到精通

前言 java路漫漫,这是一份针对java服务端开发入门与进阶指南。 建议: 尽量用 google 查找技术资料。 有问题在 stackoverflow 找找,大部分都已经有人回答。 多看官方的技术文档。 ibm deve...

rock912
2016/07/04
135
4

没有更多内容

加载失败,请刷新页面

加载更多

Git

指令 git init :创建版本库,生成.git文件夹 git add XX:上传代码到暂存区 git state:查看目前本地工作起、暂存区、分支,三者之间的文件状态 git diff demo.html:查看工作区和暂存区的代码...

Hui先生
36分钟前
6
0
绘制流程图用什么软件好?分享绘制流程图的简单方法

绘制流程图一般有两种方法,一种是手绘,另一种是利用画图工具进行绘制,更多的人们选择使用第二种方法进行绘制,方便简单。那绘制流程图用什么软件好?若是使用电脑进行绘制,可以选择迅捷画...

百因必有果
39分钟前
8
0
PHP制作的掷色子点数抽奖游戏实例

PHP制作的掷色子点数抽奖游戏实例,通过掷色子点数来达到抽奖的效果,为抽奖活动增添一些趣味性。 我们将在html页面中写下如下的html结构代码,.wrap用来放置色子和提示信息,#prize则是用来...

ymkjs1990
51分钟前
5
0
宝塔免费版部署

宝塔免费版部署 NiuSHOP安装环境及宝塔一键部署免费版 1、Niushop安装环境 操作系统:支持Windows和linux 服务器:支持Apache/Nginx/IIS服务器 PHP5.6版本及以上,最高支持PHP7.2,MySQL版本...

Geek-Chic
今天
5
0
MySQL查询优化临时表

【理论分析】 MySQL在执行SQL查询时可能会用到临时表,一般情况下,用到临时表就意味着性能较低。 临时表存储 MySQL临时表分为“内存临时表”和“磁盘临时表”,其中内存临时表使用MySQL的M...

1只特立独行的猪
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部