实操:Java 大牛带你梳理 dubbo 的那些底层原理,再也不怕被坑了

今日分享开始啦,请大家多多指教~
就目前来看,dubbo 框架是一个目前位置非常优秀的 RPC 框架, 一个必须要学的一个框架。也许以后它会更加优秀,也许会落寞。但是其设计思想,非常值得开发者去学习。
如果在一个项目中有两个 service。userService 和 orderService。我们想要其中一个 service 调用另一个。

我们大概会有如下写法:

随着业务的逐渐复杂,在开发中肯定会有业务拆分。初步是通过 maven 进行模块的拆分。

如下图,才是我们最终想要的方案,对于这种方案,orderService 端,我们称之为服务提供者,调用 orderService 的端,我们称之为服务消费者。这种思想,也为 dubbo 的出现埋下了伏笔。

jvm 的 userService 如何调用 orderService 呢?
在 java 远程调用多年的沉淀,一个接着一个框架的出现,在一点点地优化这个调用的过程。
首先是 socket 调用。在 orderService 中开放 socket 服务,在 userService 中进行远程调用。
优点:解决了单机调用的问题。
缺点:代码复杂,不易于扩展。
这可能是最初的一个远程调用解决方案,笔者不曾遇到过纯 socket 调用的框架。
如何跨语言调用?
我们发现,在 java 的对象是不可以直接通过 socket 进行传输的,需要有一个序列化的过程。而且 java 的默认的序列化,是无法被其他语言解析的。这样导致如果有其他语言提供的服务,是无法通过 java 调用。因此对于 socket 进行了升级,通过 http+xml 进行信息的传输。这就出现了 webservice。
Web Service 技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据 Web Service 规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。
Web Service 虽然早期很多人使用,但是到现在看来,这是一种过时的框架。因为,同样的一些数据,通过 json 会比 xml 少很多。通过 json 会更少的占用带宽。如下面数据。


内部调用协议
http 协议是应用层的一种协议,对于开放给外部系统时,是一个很好的选择,它可以实现跨语言调用。如果是自己的 java 服务内部调用时,使用 http 协议,就有点浪费资源。

如上图,http 协议在交互之前需要进行 tcp 三次握手,握手成功之后进行数据传输。一个 http 交互下来,有请求头、请求体、响应头、响应体。这些数据,在内部调用时,很多无关紧要的数据。也许可以自定义协议,简化传输数据。这就出现了 dubbo 协议,一种内部调用的协议。
dubbo 协议追求的是数据量小,小则快,协议的设计也符合 dubbo 框框架的理念,适用与内部服务之间的数据交互。安全性就没有 https 做得那么好,但是也不需要,毕竟 dubbo 协议设计的初衷就是内部使用的。

spring cloud 的 feign 组件内部使用 http 协议,内部调用可能有一些资源的浪费,但是 http 协议可以实现跨语言调用。
RPC 框架
对于一个 RPC 框架来说,只是能完成远程调用,并不算完美。

一般开发一个服务需要多个机器进行部署,为了防止出现单点故障。对于一个较为完善的 RPC 框架来说,在多个机器提供同样的一个服务的时候,需要自动做出选择。好比上图,userServuce 在调用 orderService 的时候,需要自动识别集群信息,并且自动选择机器进行调用。
目前,orderService 只有一个服务,三台机器,也许可以在 userServuce 中配置三个 ip,然后自行编写路由规则即可。但是随着业务的复杂,机器的变化,也许,我们起初无法得知机器的 ip 信息。

为了实现动态的机器添加与移除。最终,添加了一个机器的协调者,所有开放服务的机器在这个协调者中添加自己的开放服务的信息,这个协调者中会有哪些机器开放了哪些服务。这样看来这个协调者类似一个"通讯录"。我们称这个"通讯录"为注册中心。
这样一个较为完善的 RPC 框架,就有了雏形。
服务提供者启动之后向注册中心,提交自己提供服务的信息。
服务消费者,在消费时,去注册中心查询是否有机器提供对应的服务。例如调用 orderService 时,可以发现有 192.168.1.1 和 192.168.1.2 机器有提供对应的服务。消费者可以根据随机、轮训等规则选择调用哪个服务。
在有服务上线或者下线时,注册中心可以对修改的信息进行通知。
这样一套流程下来,就完美地实现的服务的动态部署,可以任意部署服务。
注册中心的选择
作为协调者的注册中心,占据着一个重要地位。这样来看,注册中心主要实现了临时数据存储的功能。可以有多种选择数据库、redis、zookeeper、eureka、nacos、或者自己实现。
期初 dubbo 框架官方推荐使用 zookeeper 为注册中心,出现 nacos 之后,逐渐从 zookeeper 转为 nacos。
为什么 zookeeper 转为 nacos?
结论为:zookeeper 在大数据计算时做注册中心是一个好的选择,但是在服务调用时,也许数据不需要超强的一致性。nacos 是目前来说很友好的一个注册中心,他提供了 CP+AP。还有可视化界面,还有配置中心等功能。功能相当完善。
springcloud 与 dubbo 的历史
在 17 年时,这两个词才进入我的视线。当时还有一个超级火的 springboot。那个时候招聘,几乎每个岗位都要求会 springboot。一时间,成为了一个 java 开发的必备功底。
由于 springboot 在大大开发了开发的速度,而且 springcloud 的各个组件都比较完善,feign、网关、配置中心、熔断等等。spring、springcloud 和 springboot 明显是一家人。这让一个孤身的 dubbo 有点不好立足,一些公司从 dubbo 框架转为 springcloud 全家桶。
2018 年 7 月份,eureka 停止更新。 就目前来说 eureka 的功能单单作为注册中心,已经足够优秀了。但是对于节奏如此快的互联网时代,停止更新,就意味着会慢慢地消失。
2019 年 7 月 24 日晚,Spring Cloud 官方发布公告 Spring Cloud Alibaba 即将毕业。提供了很多组件,对于大部分开发者而言,nacos、dubbo、seata 应该是较为常用的组件。
nacos:注册中心。
dubbo:一个基于 Java 的高性能开源 RPC 框架。
seata:一种高性能且易于使用的分布式事务解决方案,可用于微服务架构。
nacos 是一个新推出的注册中心,其中最亮眼的功能是提供了可视化界面,而且还附带配置中心。瞬间 dubbo 就找到了家人。这些组件的出现让 dubbo 又崛起了起来。而且 dubbo 本来扩展性就很好。可以进行协议扩展、调用拦截扩展、引用监听扩展、集群扩展等等
另外 dubbo3.0 主力使用 Triple 协议。完整兼容 gRPC over HTTP/2。推荐使用 protobuf 作为默认序列化,在性能和跨语言上的效果都会更好。
结束语
不管 maven 如何拆分,都始终是在一个 jvm 中运行, 这样只是在代码开发时会清楚方便一点。但是,某一个 service 在有较大压力的情况下,没有办法单单对此 service 做出调整。最终,我们是想要 userService 和 orderService 在不同的 jvm 中运行,如果 orderService 访问较多,我们可以只对它进行扩容。
今日份分享已结束,请大家多多包涵和指点!
评论