1、preWrite在处理和写响应之间调用postWrite在写响应之后调用asyncComplete当一个异步函数成功完成调用时调用handlerError如果处理函数抛出没有定义的异常就会调用此函数最后一个类就是TProcessorContextFreer类,这个类是一个帮助类,帮助生成的代码来释放上下文资源。第二节 基于框架生成的服务实例分析本节将对scribe服务器采用的服务实现进行详细分析。1 接口定义语言文件(IDL)(1)Facebook内部共用服务协议主要有两个文件,一个是在Thrift中定义,是用于Facebook内部的一些接口服务定义,这个不仅仅用于scribe服务器,可能还用
2、于Facebook内部其他系统,这个文件内容如下: 1 namespace java com.facebook.fb303 2 3 namespace cpp facebook.fb303 4 5 namespace perl Facebook.FB303 6 7 enum fb_status 8 9 DEAD = 0,10 11 STARTING = 1,12 13 ALIVE = 2,14 15 STOPPING = 3,16 17 STOPPED = 4,18 19 WARNING = 5,20 21 22 23 service FacebookService 24 25 string
3、getName(),26 27 string getVersion(),28 29 fb_status getStatus(),30 31 string getStatusDetails(),32 33 map getCounters(),34 35 i64 getCounter(1: string key),36 37 void setOption(1: string key, 2: string value),38 39 string getOption(1:40 41 map getOptions(),42 43 string getCpuProfile(1: i32 profileDu
4、rationInSec),44 45 i64 aliveSince(),46 47 oneway void reinitialize(),48 49 oneway void shutdown(),50 51 上面这个IDL文件定义了一个枚举类型用于表示服务的状态,还定义了一个名位FacebookService的服务,里面定义了各种操作,如获取服务状态的操作、得到计数的操作等等。下面我们来看看根据这个IDL文件生成的C+代码是什么样的一个架构。首先生成了一个基于上面服务定义的抽象类如下:class FacebookServiceIf public: virtual FacebookService
5、If() virtual void getName(std:string& _return) = 0; virtual void getVersion(std: virtual fb_status getStatus() = 0; virtual void getStatusDetails(std: virtual void getCounters(std:map & virtual int64_t getCounter(const std: key) = 0; virtual void setOption(const std: key, const std: value) = 0; virt
6、ual void getOption(std: _return, const std: virtual void getOptions(std:string, std:string virtual void getCpuProfile(std: _return, const int32_t profileDurationInSec) = 0; virtual int64_t aliveSince() = 0; virtual void reinitialize() = 0; virtual void shutdown() = 0;注意观察,除了这个类多了一个虚析构函数,其他函数就是IDL中定义
7、的。接着定义了类FacebookServiceNull,这个是上面那个抽象类的空实现(就是所有方法都没有做具体的事情),这样做的好处就是我们需要重写一些函数的时候只需要关注我们需要写的函数,而不是重写所有函数。接着又定义了封装每一个函数参数的相应类,就是一个函数的参数都用一个类来封装定义,函数的返回值也是这样处理。这样做的目的是统一远程调用的实现接口,因为传递参数都只需要这个封装类的对象就可以了。所以你会看到每一个服务里面定义的函数都有下面一组类的定义: 1 (1)class FacebookService_getName_args 3 (2)class FacebookService_get
8、Name_pargs 5 (3)typedef struct _FacebookService_getName_result_isset _FacebookService_getName_result_isset; 7 (4)class FacebookService_getName_result 9 (5)typedef struct _FacebookService_getName_presult_isset _FacebookService_getName_presult_isset;11 (6)class FacebookService_getName_presult上面这六个类定义就
9、是为服务中的getName函数服务的,相应的每一个函数都会有这种类似的定义和实现。接下来就会定义三个具体实现IDL定义的功能的类,一个客户端的类,它继承定义的服务抽象类,每一个具体的函数实现都是同样的方式和思路,同样我结合getName函数的实现来看看这个过程,其他函数都是这样实现的,代码如下:1 send_getName();3 recv_getName(_return);由上面代码可以看出首先调用函数发送函数名称及相关信息到远程,然后接受函数调用的返回值,发送函数send_getName()的代码如下: 1 int32_t cseqid = 0; 3 oprot_-writeMessage
10、Begin(getName, :apache:thrift:T_CALL, cseqid);/写一个函数调用消息RPC 5 FacebookService_getName_pargs args; 7 args.write(oprot_);/写入参数 9 oprot_-writeMessageEnd();11 oprot_-getTransport()-writeEnd();13 oprot_-flush();/保证这次写入过程立即生效上面代码就完成了函数名称以及参数的传输,调用的是TProtocol相关的类的函数实现,具体的实现内容和方式会在TProtocol部分介绍。下面接着看一下接收返回值
11、的函数recv_getName的代码: 1 int32_t rseqid = 0;/接收的消息序列号 3 std:string fname;/函数名称 5 :TMessageType mtype;/消息的类型(调用(T_CALL)、异常(T_EXCEPTION)等) 7 iprot_-readMessageBegin(fname, mtype, rseqid);/从返回消息读取函数名称、消息类型 9 if (mtype = :T_EXCEPTION) /处理异常消息11 :TApplicationException x;13 x.read(iprot_);15 iprot_-readMessa
12、geEnd();17 iprot_-readEnd();19 throw x;23 if (mtype != :T_REPLY) /处理返回消息25 iprot_-skip(:T_STRUCT);27 iprot_-29 iprot_-31 33 if (pare() != 0) /看是否是我们需要的函数名,不是就跳过消息读取35 iprot_-37 iprot_-39 iprot_-41 43 FacebookService_getName_presult result;45 result.success = &_return;47 result.read(iprot_);/读取函数返回值4
13、9 iprot_-51 iprot_-52 53 if (result._isset.success) /成功就返回结果(已经在_return里面),否则抛出异常54 55 return;56 57 58 59 throw :TApplicationException(:TApplicationException:MISSING_RESULT, getName failed: unknown result);上面代码就是处理远程调用的返回结果,代码里面有注释。一个服务函数的实现大概流程已经展现在我们面前了,处理的过程也已经清晰。这个只是用于客户端的处理流程,必须通过有效的机制来通知服务器端调用
14、相应的函数(这就是RPC)在服务器端完成相应功能并将结果返回。这种机制就是通过我们这部分介绍的TProcessor类实现,这就是上面提到三个类中的第二个类,在这个实例中是FacebookServiceProcessor类,它从TProcessor类继承,重点实现两个函数process和process_fn,其中process会调用process_fn函数来处理客户端具体调用的那个服务函数,process函数定义如下: 1 bool FacebookServiceProcessor:process(boost: : piprot, 3 boost: poprot, void* callConte
15、xt) TProtocol* iprot = piprot.get(); 7 :TProtocol* oprot = poprot.get(); 9 std:13 int32_t seqid;15 iprot-readMessageBegin(fname, mtype, seqid);/读取得到函数名称、消息类型和函数序列号17 /处理不是函数调用消息的情况19 if (mtype !T_CALL & mtype !T_ONEWAY) 21 iprot-23 iprot-25 iprot-27 :TApplicationException x(:INVALID_MESSAGE_TYPE);29
16、 /写入(返回)一个异常信息给调用客户端,客户端会根据返回结果处理异常31 oprot-writeMessageBegin(fname, :T_EXCEPTION, seqid);33 x.write(oprot);35 oprot-37 oprot-39 oprot-41 return true;43 45 return process_fn(iprot, oprot, fname, seqid, callContext);/调用实际的函数处理47 上面代码有比较详细的注释,还需要说明一点的就是如果传递的不是函数调用的消息类型就会返回给客户端一个异常的消息,客户端的接收返回值的函数就会根据收
17、到的异常消息做相应处理,上面getName函数的接收返回值函数就是抛出一个服务器端给的异常信息。下面继续看最终服务器端调用相应映射函数的处理,这个是通过process_fn函数实现:具体定义如下:process_fn(:TProtocol* iprot, 3 :TProtocol* oprot, std: fname, int32_t seqid, void* callContext) 5 /定义个map的迭代器,用于接收在函数映射查找到的映射函数 7 std:string, void (FacebookServiceProcessor:*)(int32_t, :TProtocol*, 9 :
18、TProtocol*, void*)iterator pfn;11 pfn = processMap_.find(fname);/根据函数名称查找对应的映射处理函数13 if (pfn = processMap_.end() /如果没有找到,做下面的处理17 iprot-19 iprot-21 /抛出一个不知道的方法的异常23 :UNKNOWN_METHOD, 25 Invalid method name: +fname+27 /写入到调用客户端29 oprot-31 x.write(oprot);33 oprot-39 return true;43 (this-*(pfn-second)(s
19、eqid, iprot, oprot, callContext);/调用具体的函数(RPC过程完成)45 return true;上面这个函数最终完成了RPC的过程,那个函数与映射函数的对应关系的map结构是在构造函数中初始化的,所以可以找到,例如我们举例的getName函数是下面这样初始化的:1 processMap_ = &FacebookServiceProcessor:process_getName;和getName函数一样,对于IDL定义的每一个函数在FacebookServiceProcessor类中都有一个映射的处理函数,为了展示一个完整的处理过程我们在看看getName函数的映
20、射处理函数process_getName,它的定义如下: 1 void FacebookServiceProcessor:process_getName(int32_t seqid,TProtocol* iprot, :TProtocol* oprot, void* callContext) 5 7 void* ctx = NULL; 9 if (eventHandler_.get() != NULL) 11 /得到上下文调用环境13 ctx = eventHandler_-getContext(FacebookService.getName, callContext);15 17 /定义并初始化一个用于释放资源的帮助类对象19 :TProcessorContextFreer freer(eventHandler_.get(), ctx, 21 if (eventHandler_.get() !23 eventHandler_-preRe
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2