大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说Node 调用 dubbo 服务的探索及实践,希望您对编程的造诣更进一步.
1. 背景介绍
我们公司是杭州的一家电商公司,公司内的技术体系较多,主要语言有了JAVA/PHP/Node,其中在19年的时候,公司制定了去PHP化的计划,将后端逻辑沉淀到Java服务化当中,而部分服务化调用相关业务则需要Node扛起,而与Java进行通信则需要经过Dubbo,由此我们以Consumer的角色来探索与研究如何用Node调用Dubbo.
2.Dubbo简介
2.1 什么是dubbo
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
2.2 流程图
- Provider : 暴露服务的服务提供方。
- Consumer : 调用远程服务的服务消费方。
- Registry: 服务注册与发现的注册中心。
- Monitor: 统计服务的调用次调和调用时间的监控中心。
- Container: 服务运行容器。
3. 具体实现
3.1 协议选择
官方虽然支持了很多种协议,但是真正适合于我们的协议并不是很多,譬如rmi协议主要是面向Java工程之间的调用,并不适合用于异构语言RPC场景,所以我们接下来只针对部分协议进行分析,并结合我们的实际的业务场景,最后来筛选出适合我们的协议.
连接个数 | 连接方式 | 传输协议 | 传输方式 | 序列化 | 适用范围 | 适用场景 | |
---|---|---|---|---|---|---|---|
dubbo | 单连接 | 长连接 | TCP | NIO 异步传输 | Hessian 二进制序列化 | 传入传出参数数据包较小,消费者比提供者个数多,单一消费者无法压满提供者 | 常规远程服务方法调用 |
rmi | 多连接 | 短连接 | TCP | 同步传输 | Java 标准二进制序列化 | 传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。 | 常规远程服务方法调用,与原生RMI服务互操作 |
hessian | 多连接 | 短连接 | HTTP | 同步传输 | Hessian二进制序列化 | 传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。 页面传输,文件传输,或与原生hessian服务互操作 | |
http | 多连接 | 短连接 | HTTP | 同步传输 | 表单序列化 | 传入传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传入参数 需同时给应用程序和浏览器 JS 使用的服务。 | |
rest | 多连接 | 短连接 | HTTP | 同步传输 | 表单序列化 | 同http,适用于更加符合rest规范的服务 | 同http |
3.1.1 协议选择 – dubbo
从使用场景上来看,dubbo协议是比较符合我们实际业务需求的,由于其数据包相较于Http协议体积小很多,传输速度也会更快,另外我们可以通过socket与provider建立长连接,可以减少反复建连带来的不必要的网络开销.使用此协议,我们需要注意的几个点是
- 本地负载均衡策略
- 与Provider建立TCP长连接
- Hessian协议解析
小结 : 如果想要采用此协议连接Provider,可以使用dubbo官方推荐dubbo2.js
3.1.2 协议选择 – rest
此协议是基于http,所以对consumer端就基本上没有了限制.而且此协议我们在拼接好参数之后,可以直接通过浏览器或者是HTTP请求工具即可查看结果,使用友好程度上来讲,会优于dubbo. consumer端可以直接使用request库请求,也不存在协议解析以及socket状态维护的问题,消费端的代码实现难度也会比较小.使用此协议,我们需要注意的几个点 :
- 需要使用keep-alive来与provider保持建连,否则http反复断开重连会带来很多不必要的网络开销
- 本地负载均衡策略
- 此协议在dubbo 2.6.x+ 才支持
小结 : 性能上虽不及dubbo.但对开发人员相对友好,可以结合业务自身场景进行选择.
3.1.3 补充
dubbo是支持一个服务以多种协议注册,比如一个服务可以同时注册dubbo://
和rest://
,如果你想用http,但是目前公司所暴露出来的协议只支持dubbo,可以和提供服务的同学商量一下,额外再添加一个http协议成本也是能在接收范围内的.
3.2 如何引用服务
目前引用服务有两个方案,分别是
- 直接引用
- 通过注册中心引用服务
3.2.1 直接引用服务
直接引用服务,顾名思义就是绕开注册中心获取我们所想要的服务提供者,由于绕开了注册中心,自然也无法做到服务发现,而且由于单点问题,无法做到负载均衡以及高可用,所以生产环境不推荐使用此模式的
.
但是由于其开发上的便利性,在开发环境/测试环境仍可以尝试使用此模式.
由上图所示,开发同学联调过程中,需要在项目工程中对指定服务开发同学的机器进行直连,而其他没有指定的服务将会默认走注册中心.为了避免对工程代码的侵入性,我们会在工程中建立应对不同环境的dubbo.properies,而dubbo.properies不会加入到工程的版本控制当中,主要用于解决不同环境下的服务直连问题.其中服务的控制粒度可以精确到具体的服务.
3.2.2 通过注册中心引用服务
通过注册中心发现引用服务,Dubbo常用的引用服务方式,可以做到服务自动发现,负载均衡.正式环境调用基本基于此模式.其中注册中心实现有很多种,例如Zookeeper/Redis/Multicast.官方推荐Zookeeper.
3.3 服务请求结构的定义
服务请求体结构,是在对dubbo在注册中心上注册信息的抽象之后的一层封装,一方面可以提升开发人员的开发效率,另外降低开发人员自身手动拼接请求的错误率.
3.3.1 服务的构成
我们基于dubbo/rest两种协议,来分析一下这两种协议在注册中心注册包含哪些信息.
- dubbo :
dubbo://192.168.1.2:10880/com.service.ProductService?dubbo=2.8&methods=getById,getByName
- rest :
rest://192.168.1.2:10081/service/com.service.ProductService?dubbo=2.8&methods=getById,getByName
我们对这两个协议公共部分进行提取一下
- protocol : 协议类型.例如
dubbo://
. - host : provider主机地址
- port : provider对外暴露服务的端口
- interface : 对外暴露服务名称,在java中是采用包名 + 服务名称构成,例如
com.service.ProductService
- dubboVersion: dubbo版本
- method:服务对外暴露的方法,一个服务会同时包含多个方法.
- query:还有一个就是请求参数列表,此项是在java服务定义的,在注册信息中无法体现.
3.3.2 请求体的定义
基于上述服务结构构成的分析,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不需要.
3.4 服务定义的维护
我们在对服务定义完成之后,接下来就会面临一个使用上的问题,最直接的方法就是为每个工程每个服务新建一个服务文件,但是一用就会发现一个问题请求定义的文件分散在不同工程,无法进行统一维护升级,维护成本较高.
我们第一个反应是每个服务抽象出来,各自成为一个独立的NPM包,譬如MemberService我们可以抽象成为@dubbo-service/member-service
,这样就可以解决文件分散在不同工程导致的维护问题.
3.4.1 后续问题
事情到这里,我们已经解决了服务如何统一定义的问题,但是仍然没有解决统一管理与维护的问题.如 :
- 维护人员职责划分问题.NPM包的维护工作该交给服务提供方还是服务调用方?
- 项目迁移成本问题.如果涉及到项目迁移问题,可能会涉及到很多现有的Java服务初始化的问题,而手动去定义服务工程量巨大,如何降低迁移成本问题是我们不得不要面临的问题.
4 最后
如果你觉得此篇文章对你有帮助,就顺手点个赞吧~ 非常感谢
有什么疑问可以直接评论回复或者私信我,我会尽我所能回复你~
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/12982.html