libthrift0.9.0解析(二)之TSimpleServer
TSimpleServer简单实现Tserver,代码如下。
/**
* Simple singlethreaded server for testing.
*
*/
public class TSimpleServer extends TServer { private static final Logger LOGGER = LoggerFactory.getLogger(TSimpleServer.class.getName()); private boolean stopped_ = false; public TSimpleServer(AbstractServerArgs args) {
super(args);
} public void serve() {
stopped_ = false;
try {
serverTransport_.listen(); // 开启监听
} catch (TTransportException ttx) {
LOGGER.error("Error occurred during listening.", ttx);
return;
} // Run the preServe event
if (eventHandler_ != null) {
eventHandler_.preServe(); // 前处理切入
} setServing(true); while (!stopped_) {
TTransport client = null;
TProcessor processor = null;
TTransport inputTransport = null;
TTransport outputTransport = null;
TProtocol inputProtocol = null;
TProtocol outputProtocol = null;
ServerContext connectionContext = null;
try {
client = serverTransport_.accept(); // 获得一个client transport
if (client != null) { // 以下代码根据获取的client transport层层封装
processor = processorFactory_.getProcessor(client); // 根据client获取processor
inputTransport = inputTransportFactory_.getTransport(client); // 根据client获取input transport
outputTransport = outputTransportFactory_.getTransport(client); // 根据client获取output transport
inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); // 根据input transport获取input protocol
outputProtocol = outputProtocolFactory_.getProtocol(outputTransport); // 根据output transport获取output protocol
if (eventHandler_ != null) {// 处理前切入eventHandler根据input/output protocol生成connectionContext
connectionContext = eventHandler_.createContext(inputProtocol, outputProtocol);
}
while (true) {// 一直循环处理同一个用户的请求,processor.process永远返回true,只有抛出异常时(即用户端主动关闭连接)才会继续接收下一个用户的请求。
if (eventHandler_ != null) {// 切入eventHandler处理前面生成的connectionContext
eventHandler_.processContext(connectionContext, inputTransport, outputTransport);
}
if(!processor.process(inputProtocol, outputProtocol)) {// 调用processor对input/output protocol进行处理
break;
}
}
}
} 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);
}
} if (eventHandler_ != null) {
eventHandler_.deleteContext(connectionContext, inputProtocol, outputProtocol);
} if (inputTransport != null) {
inputTransport.close();
} if (outputTransport != null) {
outputTransport.close();
} }
setServing(false);
} public void stop() {
stopped_ = true;
serverTransport_.interrupt();
}
}
首先,开启监听,然后在处理之前面向切面切入前处理流程 eventHandler_.preServe();最后进入接收处理流程。
处理时关键看第54行processor.process()函数。
TProcessor为一单接口,仅含process方法。其子类thrift不再提供,而是根据用户自定义的thrift IDL文件自动生成。然而thrift提供了一个抽象类TBaseProcessor<I>封装了一些常用的实现,该类实现了TProcessor接口,框架自动生成的Processor都继承了该基类。
TBaseProcessor<I>代码如下:
public abstract class TBaseProcessor<I> implements TProcessor {
private final I iface; // 真正的处理函数实现
private final Map<String,ProcessFunction<I, ? extends TBase>> processMap; protected TBaseProcessor(I iface, Map<String, ProcessFunction<I, ? extends TBase>> processFunctionMap) {
this.iface = iface;
this.processMap = processFunctionMap;
} public Map<String,ProcessFunction<I, ? extends TBase>> getProcessMapView() {
return Collections.unmodifiableMap(processMap);
} @Override
public boolean process(TProtocol in, TProtocol out) throws TException {
TMessage msg = in.readMessageBegin(); // 获取请求信息,主要包含函数名信息。
ProcessFunction fn = processMap.get(msg.name); // 根据函数名信息获取相应的处理函数。
if (fn == null) { // 若没有相关的处理函数,写入异常并返回。
TProtocolUtil.skip(in, TType.STRUCT);
in.readMessageEnd();
TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, "Invalid method name: '"+msg.name+"'");
out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));
x.write(out);
out.writeMessageEnd();
out.getTransport().flush();
return true;
}
fn.process(msg.seqid, in, out, iface); // 处理请求
return true;
}
}
ProcessFunction为一抽象类,其子类也是根据IDL自动生成。与IDL中的函数一一对应,为代理处理器。
TBase为IDL中定义的types的基类。T封装了处理函数的参数信息,其子类也是框架根据IDL自动生成。
public abstract class ProcessFunction<I, T extends TBase> {
private final String methodName; private static final Logger LOGGER = LoggerFactory.getLogger(ProcessFunction.class.getName()); public ProcessFunction(String methodName) {
this.methodName = methodName;
} public final void process(int seqid, TProtocol iprot, TProtocol oprot, I iface) throws TException {
T args = getEmptyArgsInstance(); // 获取一个空的参数封装
try {
args.read(iprot); // 从input protol中读取所有参数到args中
} 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 = null; try {
result = getResult(iface, args); // 获取处理结果
} catch(Throwable th) {
LOGGER.error("Internal error processing " + getMethodName(), th);
TApplicationException x = new TApplicationException(TApplicationException.INTERNAL_ERROR,
"Internal error processing " + getMethodName());
oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid));
x.write(oprot);
oprot.writeMessageEnd();
oprot.getTransport().flush();
return;
} if(!isOneway()) {// true表示单向操作不许要返回信息,即函数为void类型。false表示需要返回值,则启用output protol写入结果。
oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.REPLY, seqid));
result.write(oprot);
oprot.writeMessageEnd();
oprot.getTransport().flush();
}
} protected abstract boolean isOneway(); public abstract TBase getResult(I iface, T args) throws TException; public abstract T getEmptyArgsInstance(); public String getMethodName() {
return methodName;
}
}
到此为止,基本了解了libthrift的大致框架。在处理函数中主要是与protocol打交道,protocol又是根据input/output transport生成,而input/output transport又是根据client transport生成。总形成三层结构,底层是client transport由server transport的accept函数获得,中层是input/output transport ,顶层是input/output protocol。然而三层之间并不是完全透明不可见的,典型如oprot.getTransport().flush() 对上层暴露了底层,也无伤大雅。
下节介绍protocol以及transport。
libthrift0.9.0解析(二)之TSimpleServer的更多相关文章
- libthrift0.9.0解析(四)之TThreadPoolServer&ServerContext
TThreadPoolServer直接继承自TServer,实现类serve和stop操作. 在serve中可以接受多个连接,每个连接单独开一个线程进行处理,在每个线程中,按顺序处理该线程所绑定连接的 ...
- libthrift0.9.0解析(三)之TProtocol&TTransport
以上是transport和protocol的类图和结构图. transport封装了底层的传输通道,主要有read/write.open/close等基本的读写方法,而且都是对于二进制数据. p ...
- libthrift0.9.0解析(五)之TNonblockingServer&THsHaServer
本文是一边看代码一边写的,是真随笔,随看随下笔. 看TNonblockingServer,先看其父类AbstractNonblockingServer.一般来说,父类封装的都是通用的东西,具体的底层实 ...
- libthrift0.9.0解析(一)之TServer
TServer 属性serverTransport 为TServerTransport类型,类图如下: 构造函数,简单根据args设置几个成员,大部分是工厂类: protected TServer(A ...
- Fixflow引擎解析(二)(模型) - BPMN2.0读写
Fixflow引擎解析(四)(模型) - 通过EMF扩展BPMN2.0元素 Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件 Fixflow引擎解析(二)(模型) - BPMN ...
- C#使用zxing,zbar,thoughtworkQRcode解析二维码,附源代码
最近做项目需要解析二维码图片,找了一大圈,发现没有人去整理下开源的几个库案例,花了点时间 做了zxing,zbar和thoughtworkqrcode解析二维码案例,希望大家有帮助. zxing是谷歌 ...
- Java生成与解析二维码
1.下载支持二维码的jar包qrcode.jar和qrcode_swetake.jar, 其中qrcode_swetake.jar用于生成二维码,rcode.jar用于解析二维码,jar包下载地址(免 ...
- java 生成和解析二维码
public class QRCode { /** * 解析二维码(QRCode) * @param imgPath * @return */ public static String decoder ...
- java代码生成二维码以及解析二维码
package com.test; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedI ...
随机推荐
- 基于Redis的CAS服务端集群
为了保证生产环境CAS(Central Authentication Service)认证服务的高可用,防止出现单点故障,我们需要对CAS Server进行集群部署. CAS的Ticket默认是以Ma ...
- 『GitHub』Git常用命令记录
Commands: git init 把当前目录变成Git可以管理的仓库 随后出现.git目录,这个目录是Git来跟踪管理版本库的git commit -m "change message& ...
- hdu 4545 魔法串
http://acm.hdu.edu.cn/showproblem.php?pid=4545 #include <cstdio> #include <cstring> #inc ...
- StateListDrawable 资源
StateListDrawable 用于组织多个 Drawable 对象.当使用 StateListDrawable 作为目标组件 的背景.前景图片时,StateListDrawable 对象所显示的 ...
- keil优化等级设置
附表:Keil C51中的优化级别及优化作用 级别说明 0 常数合并:编译器预先计算结果,尽可能用常数代替表达式.包括运行地址计算. 优化简单访问:编译器优化访问8051系统的内部数据和位地址. 跳转 ...
- RandomAccessFile和memory-mapped files
[0]README 0.1) 本文描述转自 core Java volume 2, 旨在理解 java流与文件——RandomAccessFile类解析 的相关知识: 0.1) 本文 转自: http ...
- 199bit总结的影响最大的十个算法
1. 归并排序(MERGE SORT).快速排序(QUICK SORT)和堆积排序(HEAP SORT) 哪个排序算法效率最高?这要看情况.这也就是我把3种算法放在一起讲的原因,可能你更常用其中一种, ...
- POJ 1287 Networking
题目链接: poj.org/problem?id=1287 题目大意: 你被分派到去设计一个区域的连接点,给出你每个点对之间的路线,你需要算出连接所有点路线的总长度. 题目输入: 一个数字n 代表有 ...
- HDOJ 1048 The Hardest Problem Ever(加密解密类)
Problem Description Julius Caesar lived in a time of danger and intrigue. The hardest situation Caes ...
- HDU_1874——最短路问题,Dijkstra算法模版
Problem Description 某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行 ...