咱们公司是杭州的一家电商公司,公司内的技术体系较多,主要语言有了JAVA/PHP/Node,其中在19年的时候,公司制定了去PHP化的计划,将后端逻辑沉淀到Java服务化当中,而部分服务化调用相关业务则须要Node扛起,而与Java进行通讯则须要通过Dubbo,由此咱们以Consumer的角色来探索与研究如何用Node调用Dubbo.javascript
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。java
官方虽然支持了不少种协议,可是真正适合于咱们的协议并非不少,譬如rmi协议主要是面向Java工程之间的调用,并不适合用于异构语言RPC场景,因此咱们接下来只针对部分协议进行分析,并结合咱们的实际的业务场景,最后来筛选出适合咱们的协议.git
链接个数 | 链接方式 | 传输协议 | 传输方式 | 序列化 | 适用范围 | 适用场景 | |
---|---|---|---|---|---|---|---|
dubbo | 单链接 | 长链接 | TCP | NIO 异步传输 | Hessian 二进制序列化 | 传入传出参数数据包较小,消费者比提供者个数多,单一消费者没法压满提供者 | 常规远程服务方法调用 |
rmi | 多链接 | 短链接 | TCP | 同步传输 | Java 标准二进制序列化 | 传入传出参数数据包大小混合,消费者与提供者个数差很少,可传文件。 | 常规远程服务方法调用,与原生RMI服务互操做 |
hessian | 多链接 | 短链接 | HTTP | 同步传输 | Hessian二进制序列化 | 传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。 页面传输,文件传输,或与原生hessian服务互操做 | |
http | 多链接 | 短链接 | HTTP | 同步传输 | 表单序列化 | 传入传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传入参数 需同时给应用程序和浏览器 JS 使用的服务。 | |
rest | 多链接 | 短链接 | HTTP | 同步传输 | 表单序列化 | 同http,适用于更加符合rest规范的服务 | 同http |
从使用场景上来看,dubbo协议是比较符合咱们实际业务需求的,因为其数据包相较于Http协议体积小不少,传输速度也会更快,另外咱们能够经过socket与provider创建长链接,能够减小反复建连带来的没必要要的网络开销.使用此协议,咱们须要注意的几个点是github
小结 : 若是想要采用此协议链接Provider,可使用dubbo官方推荐dubbo2.js后端
此协议是基于http,因此对consumer端就基本上没有了限制.并且此协议咱们在拼接好参数以后,能够直接经过浏览器或者是HTTP请求工具便可查看结果,使用友好程度上来说,会优于dubbo. consumer端能够直接使用request库请求,也不存在协议解析以及socket状态维护的问题,消费端的代码实现难度也会比较小.使用此协议,咱们须要注意的几个点 :浏览器
小结 : 性能上虽不及dubbo.但对开发人员相对友好,能够结合业务自身场景进行选择.网络
dubbo是支持一个服务以多种协议注册,好比一个服务能够同时注册dubbo://
和rest://
,若是你想用http,可是目前公司所暴露出来的协议只支持dubbo,能够和提供服务的同窗商量一下,额外再添加一个http协议成本也是能在接收范围内的.负载均衡
目前引用服务有两个方案,分别是框架
直接引用服务,顾名思义就是绕开注册中心获取咱们所想要的服务提供者,因为绕开了注册中心,天然也没法作到服务发现,并且因为单点问题,没法作到负载均衡以及高可用,因此生产环境不推荐使用此模式的
.异步
可是因为其开发上的便利性,在开发环境/测试环境仍能够尝试使用此模式.
由上图所示,开发同窗联调过程当中,须要在项目工程中对指定服务开发同窗的机器进行直连,而其余没有指定的服务将会默认走注册中心.为了不对工程代码的侵入性,咱们会在工程中创建应对不一样环境的dubbo.properies,而dubbo.properies不会加入到工程的版本控制当中,主要用于解决不一样环境下的服务直连问题.其中服务的控制粒度能够精确到具体的服务.
经过注册中心发现引用服务,Dubbo经常使用的引用服务方式,能够作到服务自动发现,负载均衡.正式环境调用基本基于此模式.其中注册中心实现有不少种,例如Zookeeper/Redis/Multicast.官方推荐Zookeeper.
服务请求体结构,是在对dubbo在注册中心上注册信息的抽象以后的一层封装,一方面能够提高开发人员的开发效率,另外下降开发人员自身手动拼接请求的错误率.
咱们基于dubbo/rest两种协议,来分析一下这两种协议在注册中心注册包含哪些信息.
dubbo://192.168.1.2:10880/com.service.ProductService?dubbo=2.8&methods=getById,getByName
rest://192.168.1.2:10081/service/com.service.ProductService?dubbo=2.8&methods=getById,getByName
咱们对这两个协议公共部分进行提取一下
dubbo://
.com.service.ProductService
基于上述服务结构构成的分析,dubbo和rest服务请求结构构成大致相似,咱们对不一样的协议请求的能够作以下定义.
// 1. dubbo协议的请求体定义
services.ProductService = (dubbo) => dubbo.proxyService({
dubboInterface: 'com.service.ProductService',
methods: {
getById(id) {
return [java.Long(id)];
},
getByName(name) {
return [java.String(name)];
}
},
});
复制代码
// rest 请求体定义
services.ProductService = (dubbo) => dubbo.proxyService({
dubboInterface: 'com.service.ProductService',
methods: {
getById(id) {
return {
method: 'get',
query: [parseInt(id)]
};
},
getByName(name) {
return [String(name)];
}
},
});
复制代码
二者最大不一样点在于参数定义上的不一样,dubbo须要强制转换为强类型,而rest不须要.
咱们在对服务定义完成以后,接下来就会面临一个使用上的问题,最直接的方法就是为每一个工程每一个服务新建一个服务文件,可是一用就会发现一个问题请求定义的文件分散在不一样工程,没法进行统一维护升级,维护成本较高.
咱们第一个反应是每一个服务抽象出来,各自成为一个独立的NPM包,譬如MemberService咱们能够抽象成为@dubbo-service/member-service
,这样就能够解决文件分散在不一样工程致使的维护问题.
事情到这里,咱们已经解决了服务如何统必定义的问题,可是仍然没有解决统一管理与维护的问题.如 :
若是你以为此篇文章对你有帮助,就顺手点个赞吧~ 很是感谢
有什么疑问能够直接评论回复或者私信我,我会尽我所能回复你~