RPC结构泛化调用功用在网关、接口测验等场景下有着广泛的需求,本文给各位读者介绍一下干流的泛化调用完成办法及原理,比较各种完成计划的优缺陷,并共享泛化调用在转转的实践。一方面有助于RPC结构运用方了解泛化调用,更好地运用泛化调用;另一方面关于有自研RPC结构需求的开发者在挑选泛化调用完成计划上有一定参阅意义。

1 一般RPC调用

根据动态署理技能,RPC结构客户端做到了调用RPC办法与调用本地办法相同的体会。一般情况下服务端定义服务接口,并将接口打包到二方jar包发布。服务端在服务进程中完成该接口,而调用方在进程中根据该接口创立动态署理进行调用,与调用本地办法体会一起。

例如有接口HelloService,被打包在demo-service-interfaces.jar包中。

public interface HelloService {
    String hello(String name);
}

服务端依靠demo-service-interfaces.jar,创立HelloServiceImpl完成该接口。

public class HelloServiceImpl implements HelloService {
    @Override
    public String hello(String name) {
        return "hello, " + name;
    }
}

客户端相同依靠demo-service-interface.jar,创立HelloService的署理类,以下为代码示例,实际上创立署理类,发送接口、参数,接收返回结果等操作都是封装在结构内的。

HelloService helloService = (HelloService)Proxy.newProxyInstance(this.getClass().getClassLoader(), HelloService.class, (InvocationHandler) (proxy, method, args) -> {
    //都是封装在结构内的
    //获取办法、参数类型
    String methodName = method.getName();
    Class<?>[] parameterTypes = method.getParameterTypes();
    //发送办法、参数类型和实参到服务端并返回结果
    return request(methodName, parameterTypes, args);
});
String result = helloService.hello("jack");
System.out.println(result);

2 网关、接口测验等场景下的需求

由上文能够看到一般的RPC调用需求将接口类(参数和返回值如果是POJO类型相同需求一同打包)打到一个jar包中,被服务方和调用方一起依靠。这种办法在多大数事务场景中是适用的,且愈加便利,由于所依靠的接口jar包是可枚举的。

可是在一些特殊的场景下依靠接口jar包变得很不便利,比如网关、接口测验渠道等。例如运用http网关署理私有协议RPC请求,如果在网关中依靠接口jar包,那么在新增办法或许接口时网关需求从头编译上线。而接口测验渠道需求对全公司所有的RPC接口进行测验,将全公司所有的接口jar包添加到测验渠道的依靠中显然是不可行的。

在这些场景下就诞生了对泛化调用的需求。

3 泛化调用

泛化调用便是在不依靠服务方接口jar包的情况下进行调用,包括对调用办法的泛化、参数的泛化和返回值的泛化

public interface GenericService {
    Object $genericInvoke(String methodName, String[] parameterTypes, Object[] args);
}

在没有接口类依靠的情况下,parameterTypes需求经过字符串指定,而args和返回值如果是jdk内置类型的话与一般调用无异,而如果是POJO类型的话则需求寻找一种通用的表明办法。

下一般RPC调用的序列化与反序列化原理,如下图所示,实际上序列化结构在将POJO序列化成字节数组之前需求解析POJO的类结构生成序列化中间体,当然序列化中间体并非一定能在序列化结构中找到对应的类,有时候这个中间体是虚拟的。

RPC框架泛化调用原理及转转的实践

3.1 根据Java Bean的泛化调用

根据Java Bean的泛化调用是经过一致的Java Bean描绘符(JavaBeanDescriptor)来描绘POJO目标,它作业在序列化层之上,例如dubbo支撑该种类型的泛化调用,在运用泛化调用时,直接传递JavaBeanDescriptor目标作为参数,基本原理如下图所示。

RPC框架泛化调用原理及转转的实践

该泛化调用的完成通用性比较强,与底层序列化无关,可是复杂度较高,需求RPC结构处理POJOJavaBeanDescriptor之间的转化。

3.2 根据序列化中间体的泛化调用

支撑根据序列化中间体的泛化调用的RPC结构典型的如sofa-rpc,运用了sofa-hessian序列化结构,sofa-hessian是在hessian序列化结构基础上进行二次开发的,笼统出了序列化中间体,如GenericObjectGenericMapGenericArray等。

转转RPC结构在支撑泛化调用时也参阅了sofa-hessian的完成,对hessian序列化结构进行二次开发,而且有所改进。

RPC框架泛化调用原理及转转的实践

json序列化天然具备序列化中间体,即JsonObject或许json String,在运用json序列化时调用方能够直接将Json Object或许json String作为参数替代POJO进行调用。转转RPC结构也支撑根据json序列化的泛化调用。

dubbo除了支撑根据Java Bean的泛化调用,还支撑json-protobuf泛化调用,也便是说调用方能够运用json描绘protobuf目标,在反序列化时能够将json反序列为protobuf目标再转化成POJO,而这些功用自身是序列化结构所供给,不需求RPC结构做额外的开发支撑。

根据序列化中间体的泛化调用与根据Java Bean的泛化调用相比,完成较为简略,有些序列化结构自身原生就支撑,或许对序列化结构做简略的二次开发即可完成,缺陷是与序列化结构耦合。

4 泛化调用在转转的实践

现在泛化调用在转转公司运用最广泛的范畴便是接口测验,咱们供给了一致的测验API渠道。经过该渠道能够运用http + json的办法完成对恣意服务、恣意节点、恣意办法的调用,而测验API渠道不需求依靠任何服务的接口jar包。而且API渠道也没有依靠RPC结构jar包,由于转转RPC结构完成了在同一个端口上一起兼容私有的二进制协议及公有的http协议,也便是说能够运用http请求来建议RPC调用。

RPC框架泛化调用原理及转转的实践

一起还支撑获取恣意服务、恣意节点、恣意办法参数及返回值的JsonSchema,如下代码所示。

{
    "msg": "success",
    "data": {
        "schema": {
            "returnValue": {
                "type": "array",
                "items": {
                    "type": "object",
                    "id": "urn:jsonschema:com:bj58:zhuanzhuan:arch:user:atomic:entity:User",
                    "properties": {
                        "id": {
                            "type": "string"
                        },
                        "userName": {
                            "type": "string"
                        },
                        "userNamePinyin": {
                            "type": "string"
                        },
                        "mock": {
                            "type": "boolean"
                        }
                    }
                }
            },
            "parameters": {
                "pageNum": {
                    "type": "integer"
                },
                "pageSize": {
                    "type": "integer"
                }
            }
        }
    },
    "code": 0
}

未来转转的网关也将根据泛化调用进行开发。

5 总结

RPC结构的泛化调用在网关、测验渠道等范畴运用广泛,现在干流的泛化调用完成有根据Java Bean规范的泛化调用和根据序列化中间体的泛化调用,它们的优缺陷分别如下:

  • 根据Java Bean的泛化调用:优点是与序列化无关;缺陷是RPC结构需求完成JavaBeanDescriptorPOJO的转化功用,较为复杂。
  • 根据序列化中间体的泛化调用:优点是RPC结构完成简略,序列化结构原生支撑或许仅需少数改造;缺陷是与特定的序列化结构耦合。

在开发RPC结构时,具体挑选哪种泛化调用完成办法,还需求结合实际情况做出挑选。


关于作者

王建新,转转架构部服务治理担任人,首要担任服务治理、RPC结构、分布式调用盯梢、监控系统等。爱技能、爱学习,欢迎联络沟通。

转转研制中心及业界小伙伴们的技能学习沟通渠道,定期共享一线的实战经验及业界前沿的技能论题。 关注公众号「转转技能」(综合性)、「大转转FE」(专注于FE)、「转转QA」(专注于QA),更多干货实践,欢迎沟通共享~