Dubbo基础
什么是Dubbo?
Dubbo是Apache下的,一款高性能,轻量级,开源的java RPC框架。
根据Dubbo官方文档的介绍,Dubbo提供了溜达核心能力:
- 面向接口代理的高性能RPC调用
- 智能容错和负载均衡
- 服务自动扩展能力
- 高度可扩展能力
- 运行期流量调度
- 可视化的服务治理与运维
简单来说,就是Dubbo不光可以帮助我们调用远程服务,还提供了一些其它开箱即用的功能,比如说智能负载均衡。
为什么要用Dubbo?
随着互联网的发展,网络的规模越来越大,用户数量越来越多。单一应用的架构,垂直应用架构无法满足我们的需求,这个时候分布式服务架构就诞生了。
分布式服务架构下,系统被拆分成不同的服务,比如短信服务,安全服务,每个服务都独立提供系统的某个核心功能。
实际上Java中的RPC框架也有好几个,比如Java RMI,Hession等。但是我们为什么选择Dubbo呢?
因为Java RMI,Hession虽然也能实现远程调用,但是更适合两个服务之间相互调用。因为我工作以来就开始用dubbo,所以为了这篇笔记特意去搭了以上两个框架的demo,下面附上一个我觉得写的比较好的教程:Java常用的RPC框架-RMI,hessian,dubbo
大家去看下大概就能懂这两个框架的原理,其实就是最基本框的RPC封装。而且功能很少,只是单纯的暴露和引用远程服务。而且注册中心还是很直观的实现。相比于Dubbo的可视化注册中心,负载均衡,服务监控等就迫在眉睫了。所以说Dubbo更受分布式系统的青睐(相比于RMI和Hession)。
Dubbo帮助我们解决了什么问题?
- 负载均衡:同一个服务部署在不同的机器时该调用一台机器上的服务。
- 服务调用链路生成:随着系统的发展,服务越来越多,服务之间依赖关系变得错综复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。Dubbo可以为我们解决服务之间互相是如何调用的。
-
服务访问压力以及时长统计,资源调度和治理:基于访问压力实时管理集群容量,提高集群利用率。
分布式基础
什么是分布式?
分布式或者说SOA分布式重要的就是面向服务,说简单的分布式就是我们把整个系统拆分成不同的服务放在不同的服务器上,减轻单体服务的压力,提高并发量和性能。
比如电商系统可以简单地拆分成订单系统,商品系统,登录系统等。拆分之后每个服务器可以部署在不同的机器上,如果某一个服务的访问量比较大的话也可以将这个服务同时部署在多台机器上。
为什么要分布式?
从开发角度来讲,单体应用的代码都集中在一起,而分布式系统的代码根据业务被拆分。所以每个团队可以负责一个服务的开发,这样提升了开发效率。另外代码根据业务拆分之后更加便于维护和扩展。
另外,将系统拆分成分布式之后不光便于系统扩展和维护,更能提高整个系统的性能。
Dubbo架构
Dubbo架构中的核心角色有哪些?
上述节点简单介绍以及他们之间的关系:
- Container:服务运行容器,负责加载,运行服务提供者。
- Provider:暴露服务的服务提供方,会向注册中心注册自己提供的服务。
- Consumer:调用远程服务的服务消费方,会向注册中心订阅自己所需的服务。
- Registry:服务注册与发现的注册中心。注册中心会返回服务提供者地址列表给消费者。
- Monitor:统计服务的调用次数和调用时间的监控中心。服务消费者和提供者会定时发送统计数据到监控中心。
Dubbo中的Invoker概念是什么?
Invoker是Dubbo领域模型中非常重要的一个概念。简单来说就是Dubbo对远程调用的抽象:
按照Dubbo官方的话来说,Invoker分为:
- 服务提供Invoker
- 服务消费Invoker
假如我们需要调用一个远程方法,我们需要动态代理来屏蔽远程调用的细节。我们屏蔽掉的这些细节就依赖对应的Invoker实现,Invoker实现了真正的远程服务调用。下面有一篇文章我觉得讲的比较好,大家可以看看:深入理解Dubbo核心模型Invoker
Dubbo的工作原理
下图是Dubbo的整体设计,从下到上分为十层,各层单项依赖。
- Service服务层:这个就比较简单了,就是我们具体的代码逻辑,其实也算不得是Dubbo的,不多说了。
- config配置层:Dubbo相关的配置,支持代码配置,同时也支持基于Spring来做配置。以ServiceConfig,ReferenceConfig为中心。
- proxy服务代理层:调用远程方法像调用本地方法一样简单的一个关键,真实调用过程依赖代理类,以ServiceProxy为中心。
- registry注册中心层:封装服务地址的注册与发现。
- cluster路由层:封装多个提供者的路由以及负载均衡,并桥接注册中心,以Invoker为中心。
- monitor监控层:RPC调用次数和调用时间监控。以Statistics为中心。
- protocal远程调用层:封装RPC调用,以Invocation,Result为中心。
- exchange信息交换层:封装请求响应模式,同步转异步,以Request,Reponse为中心。
- transport网络传输层:抽象mina和netty为统一接口,以Message为中心。
- serialize数据序列化层:对需要在网络传输的数据进行序列化。
Dubbo的SPI机制是什么?如何让扩展Dubbo中的默认实现?
SPI(Service Provider Interface)机制被大量用在开源项目中,它可以帮我们动态寻找服务/功能的实现。
SPI的具体原理是这样的:我们将接口的实现类放在配置文件里,在程序运行过程中读取配置文件,通过反射加载实现类。这样我们可以在运行的时候,动态替换接口的实现类。和IOC的解耦思想是类似的。
java本身就提供了SPI机制的实现,不过dubbo没有直接用,而是对java原生的spi机制进行了增强,以便更好的满足自己的需求。
如何扩展Dubb中的默认实现呢?
比如说我们想要实现自己的负载均衡策略,可以创建对应的实现类xxLoadBalance实现LoadBalance接口或者AbstractLoadBalance类。
然后我们可以将这个实现类的路径写入到resources目录下的META-INF/dubbo/org.apache.dubbo.rpc.cluster.LoadBalance文件中即可。
其实dubbo还支持很多可供扩展的选择,我们可以去dubbo开发手册中查看:https://cn.dubbo.apache.org/zh/docs3-v2/java-sdk/reference-manual/spi/description/
关于Dubbo的一些小问题
-
注册中心的作用是什么?
注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互。 -
服务提供者宕机后,注册中心会做什么?
注册中心会立即推送事件通知消费者。 -
监控中心的作用呢?
监控中心负责统计各服务调用次数,调用时间等。 -
注册中心和监控中心都宕机的话,服务都会挂掉么?
不会,两者都宕机也不影响已运行的提供者和消费者。消费者在本地缓存了提供者列表。注册中心和监控中心都是可选的,服务消费者可以直连服务提供者。
Dubbo的负载均衡策略
什么是负载均衡?
假如我们系统访问量特别大,我们将这个服务部署在了多台服务器上,当客户端发生请求的时候,多台服务器都可以处理这个请求。那么如何选择处理该请求的服务器就很关键。负载均衡就是为了避免请求分配不合理而出现的。
Dubbo提供的负载均衡策略有哪些?
在集群负载均衡的时候,Dubbo提供了多种均衡策略。默认是random随机调用。我们还可以自行扩展负载均衡策略。下面是dubbo提供的几种策略。
RandomLoadBalance
根据权重随机选择,这是Dubbo默认采用的一种负载均衡策略。
这个实现原理非常简单,比如说权重满份100,S1权重12,S2权重22,S3权重76.那么就生成一个0-100的随机数。前小于12就取S1,12到22之间就取S2,22到100之间就取S3。LeastActiveLoadBalance
这个直接说原理:每一个服务提供者对应一个活跃数。这个活跃数初始值为0.收到请求活跃数+1.处理完请求活跃数-1.因此,Dubbo会优先把请求给活跃数最小的服务提供者处理。如果多个提供者活跃数相同则再走一遍RandomLoadBalance。ConsistentHashLoadBalance
一致性hash负载均衡策略。ConsistentHashLoadBalance中没有权重的概念。具体哪个服务提供者处理请求是由请求的参数决定的。也就是说相同的参数的请求总是发到同一个服务提供者上。RoundRobinLoadBalance
加权轮询负载均衡。简单可以理解成权重随机的公平版。既然是基础的权重比例。只不过这次不随机获取了,而是从前到后顺序来。
Dubbo的序列化协议
Dubbo支持多种序列化方式,比如jdk自带的序列化,hessian2,json,kryo,FST之类的。默认使用的是hessian2.
一般我们不会直接使用jdk自带的序列化方式,主要原因有两个:
- 不支持跨语言调用:如果调用的是其他语言开发的服务就不支持了。
- 性能差:相比于其它序列化框架性能更低,主要原因是序列化之后的字节数组体积较大,导致传输成本大。
JSON序列化由于性能问题,我们一般也不会考虑使用。
而Protostuff,ProtoBuf,hessian2这些都是跨语言的序列化方式,如果有跨语言需求的话可以考虑使用。
Kryo和FST是Dubbo后来才引入的,性能比较好,不过这两个都专门针对java语言的。Dubbo官网的一篇文章提到过推荐使用Kryo作为生产环境的序列化方式。
本篇笔记就到这里,反正大部分都是八股文,如果对你有所帮助就点个喜欢点个关注吧,也希望大家工作顺顺利利,身体健健康康!