RPCX分布式服务框架主要致力于提供高性能和透明化的RPC远程服务调用。
拦截器 :是在面向切面编程中应用的,就是在你的service或者一个方法前调用一个方法,或者在方法后调用一个方法。比如java的动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串。RPCX框架中并没有调用拦截的处理(扫源代码好像没看到)
拦截链:多个拦截器构成一个链,完成一组拦截,可能还有执行的先后顺序(任务职责链)。
拦截链简单实现
输入参数:
type CmdIn struct {
Param string
}
func (this *CmdIn) String() string {
return fmt.Sprintf("[CmdIn Param is %s]",this.Param)
}
输出参数:
type CmdOut struct {
Result int
Info string
}
func (this *CmdOut) String() string {
return fmt.Sprintf("Result[%d] Info[%s]",this.Result,this.Info)
}
处理Handler:
type Hello struct {
Param string
}
func (this *Hello) Test1(ctx context.Context, in *CmdIn, out *CmdOut) error {
fmt.Println("接收到服务消费方输入:",in.Param)
out.Result=12345678
out.Info="我已经吃饭了!"
return nil
}
封装Invoker:
package defines
import (
"fmt"
"context"
"reflect"
"unicode"
"unicode/utf8"
"container/list"
)
var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
var typeOfContext = reflect.TypeOf((*context.Context)(nil)).Elem()
type MethodType struct {
method reflect.Method
ArgType reflect.Type
ReplyType reflect.Type
}
type Reflect struct {
Name string
Rcvr reflect.Value
Typ reflect.Type
Method map[string]*MethodType
filter *list.List
}
func (this *Reflect) Setup(rcvr interface{}, name string,filter *list.List) {
this.Typ = reflect.TypeOf(rcvr)
this.Rcvr = reflect.ValueOf(rcvr)
this.Name = reflect.Indirect(this.Rcvr).Type().Name()
this.Method = suitableMethods(this.Typ, true)
this.filter=filter
}
func (this *Reflect) Call(ctx context.Context,service string,method string,in *CmdIn,out *CmdOut) error {
for e := this.filter.Front(); e != nil; e = e.Next() {
f:=e.Value.(Filter)
err:=f.Invoke(ctx,service,method,in,out)
if err!=nil{
return err
}
}
mtype := this.Method[method]
returnValues := mtype.method.Func.Call([]reflect.Value{this.Rcvr, reflect.ValueOf(ctx), reflect.ValueOf(in), reflect.ValueOf(out)})
errInter := returnValues[0].Interface()
if errInter != nil {
return errInter.(error)
}else{
return nil
}
}
func suitableMethods(typ reflect.Type, reportErr bool) map[string]*MethodType {
methods := make(map[string]*MethodType)
for m := 0; m < typ.NumMethod(); m++ {
method := typ.Method(m)
mtype := method.Type
mname := method.Name
if method.PkgPath != "" {
continue
}
if mtype.NumIn() != 4 {
if reportErr {
fmt.Println("method", mname, "has wrong number of ins:", mtype.NumIn())
}
continue
}
ctxType := mtype.In(1)
if !ctxType.Implements(typeOfContext) {
if reportErr {
fmt.Println("method", mname, " must use context.Context as the first parameter")
}
continue
}
argType := mtype.In(2)
if !isExportedOrBuiltinType(argType) {
if reportErr {
fmt.Println(mname, "parameter type not exported:", argType)
}
continue
}
// Third arg must be a pointer.
replyType := mtype.In(3)
if replyType.Kind() != reflect.Ptr {
if reportErr {
fmt.Println("method", mname, "reply type not a pointer:", replyType)
}
continue
}
// Reply type must be exported.
if !isExportedOrBuiltinType(replyType) {
if reportErr {
fmt.Println("method", mname, "reply type not exported:", replyType)
}
continue
}
// Method needs one out.
if mtype.NumOut() != 1 {
if reportErr {
fmt.Println("method", mname, "has wrong number of outs:", mtype.NumOut())
}
continue
}
// The return type of the method must be error.
if returnType := mtype.Out(0); returnType != typeOfError {
if reportErr {
fmt.Println("method", mname, "returns", returnType.String(), "not error")
}
continue
}
methods[mname] = &MethodType{method: method, ArgType: argType, ReplyType: replyType}
}
return methods
}
func isExportedOrBuiltinType(t reflect.Type) bool {
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
return isExported(t.Name()) || t.PkgPath() == ""
}
func isExported(name string) bool {
rune, _ := utf8.DecodeRuneInString(name)
return unicode.IsUpper(rune)
}
拦截器定义:
type Filter interface {
Invoke(ctx context.Context,service string,method string,in interface{},out interface{}) error
}
//限制用拦截器
type LimitFilter struct {
}
func (this *LimitFilter) Invoke(ctx context.Context,service string,method string,in interface{},out interface{}) error {
fmt.Println("拦截链 LimitFilter process")
return nil
}
//调用统计拦截器
type StatisticsFilter struct {
}
func (this *StatisticsFilter) Invoke(ctx context.Context,service string,method string,in interface{},out interface{}) error {
fmt.Println("拦截链 StatisticsFilter process")
return nil
}
调用示例:
func TestReflect_Setup(t *testing.T) {
filters:=list.New() //拦截链
filters.PushBack(&LimitFilter{}) //拦截组件1
filters.PushBack(&StatisticsFilter{}) //拦截组件2
hello:=&Hello{}
reflect:=&Reflect{}
reflect.Setup(hello,"Hello",filters)
fmt.Println("发起消费方调用")
in:=&CmdIn{
Param:"吃饭了吗?",
}
out:=&CmdOut{}
err:=reflect.Call(context.Background(),"Hello","Test1",in,out)
if err!=nil {
fmt.Println(err)
}else{
fmt.Println("接收到服务提供方返回:",out)
}
}
程序执行结果:
1.发起消费方调用
2.拦截链 LimitFilter process
3.拦截链 StatisticsFilter process
4.接收到服务消费方输入: 吃饭了吗?
5.接收到服务提供方返回: Result[12345678] Info[我已经吃饭了!]
系列文章