说说ApacheDubbo,概念、架构、负载均衡已经落地业界,应用广泛。Dubbo作为阿里巴巴内部SOA服务化治理解决方案的核心框架,2012年每天为2000+服务提供30亿+访问支持,广泛应用于阿里巴巴集团各成员站点。Dubbo自2011年开源以来,已经被很多非阿里巴巴公司使用,包括当当网、网易考拉等互联网公司,以及中国人寿、青岛海尔等传统企业。本文是笔者根据官方文档和自己平时的使用情况对Dubbo的总结。一个重要的概念1.1什么是Dubbo?ApacheDubbo(孵化)|d?b??|是一个高性能、轻量级的开源JavaRPC框架,提供了三大核心能力:面向接口的远程方法调用、智能容错和负载均衡、自动服务注册和发现。简单的说,Dubbo是一个分布式服务框架,致力于提供高性能透明的RPC远程服务调用解决方案和SOA服务治理解决方案。Dubbo目前拥有近25kStars,Dubbo的Github地址:https://github.com/apache/incubator-dubbo。此外,在开源中国举办的2018年度中国最受欢迎开源软件评选中,Dubbo凭借超高人气获得第三名,仅次于vue.js和ECharts。Dubbo由阿里开源,后来加入了Apache。正式由于Dubbo的出现,越来越多的公司开始使用和接受分布式架构。上面我们说了Dubbo其实是一个RPC框架,那么什么是RPC呢?1.2什么是RPC?RPC的原理是什么?什么是RPC?RPC(RemoteProcedureCall)——远程过程调用,是通过网络进行远程过程调用的一种协议,计算机程序在不了解底层网络技术的情况下请求服务。比如,两个不同的服务A和B分别部署在两台不同的机器上,那么服务A要调用服务B中的方法怎么办呢?使用HTTP请求当然是可以的,但是可能会比较慢,而且有些优化也没有做好。RPC的出现就是为了解决这个问题。RPC的原理是什么?这里简单提一下。具体可以参考以下文章:http://dubbo.apache.org/zh-cn/blog/rpc-introduction.htmlRPC示意图服务消费者(client)以本地调用方式调用服务;clientstub接收到调用后,负责将方法、参数等组装成可以在网络上传输的消息体;客户端存根找到服务地址并将消息发送到服务器;服务器存根在收到消息后对其进行解码;服务器存根根据解码结果调用本地服务;本地服务执行并将结果返回给服务器存根;服务器存根将返回结果打包成消息发送给消费者;客户端存根接收消息并对其进行解码;服务消费者获得最终结果。下一篇网上贴一张时序图:RPC原理时序图说了这么多,我们为什么要用Dubbo?1.3为什么要使用Dubbo?Dubbo的诞生与SOA分布式架构的流行有很大的关系。SOA面向服务架构(ServiceOrientedArchitecture),即项目按照业务逻辑分为服务层和表现层两个项目。服务层包含业务逻辑,只需要对外提供服务。表现层只需要处理与页面的交互,业务逻辑通过调用服务层的服务来实现。SOA架构中主要有两个角色:服务提供者(Provider)和服务使用者(Consumer)。为什么要使用Dubbo?如果要开发分布式程序,也可以直接基于HTTP接口进行通信,但是为什么要用Dubbo呢?我觉得主要从Dubbo提供的四个特性来看,你可以使用Dubbo:负载均衡——当同一个服务部署在不同的机器上时,应该调用那台机器上的服务。服务调用链接生成——随着系统的发展,服务越来越多,服务之间的依赖关系变得复杂,甚至不清楚哪个应用先启动哪个应用,架构师也无法完整描述架构应用程序的关系。Dubbo可以为我们解决服务之间如何相互调用。服务访问压力和时长统计,资源调度和治理——根据访问压力实时管理集群容量,提高集群利用率。服务降级——服务挂掉后调用备用服务另外,Dubbo不仅可以应用在分布式系统中,也可以应用在当下流行的微服务系统中。但是,由于SpringCloud在微服务中的应用更为广泛,我想大家一提到Dubbo,多半是在分布式系统的情况下。刚才我们提到了分布式的概念,那我给大家介绍一下什么是分布式?为什么要分发?1.4什么是分布式?分布式或者SOA分布式对于面向服务很重要,简单的分布式就是我们把整个系统拆分成不同的服务,把这些服务放在不同的服务器上,减少单体服务的压力,提高并发和性能。比如一个电商系统,可以简单的拆分成订单系统、商品系统、登录系统等,拆分之后,各个服务可以部署在不同的机器上。服务同时部署在多台机器上。1.5为什么要分发?从开发的角度来看,单体应用的代码集中在一起,而分布式系统的代码是按照业务拆分的。这样每个团队就可以负责一个服务的开发,提高了开发效率。另外,代码按照业务拆分后,更容易维护和扩展。另外,我认为将系统拆分成分布式的,不仅方便了系统的扩展和维护,也提高了整个系统的性能。你考虑一下吗?将整个系统拆分成不同的服务/系统,然后将每个服务/系统部署在单独的服务器上,是不是大大提高了系统性能?二Dubbo架构2.1DubboDubbo的架构图。以上节点简要说明:Provider:暴露服务的服务提供者Consumer:调用远程服务的服务消费者Registry:服务注册和发现的注册中心Monitor:统计服务调用次数的监控中心Containercalltime:服务运行容器调用关系说明:服务容器负责启动、加载、运行服务提供者。当服务提供者启动时,它向注册中心注册它提供的服务。当服务消费者启动时,它向注册中心订阅它需要的服务。注册中心将服务提供者地址列表返回给消费者。如果有变化,注册中心会基于长连接将变化数据推送给消费者。服务消费者,从提供者地址列表中,根据软负载均衡算法选择一个提供者调用,如果调用失败,再选择另一个提供者调用。服务消费者和提供者在内存中累积调用次数和调用时间,每分钟定时向监控中心发送统计数据。重要知识点总结:注册中心负责服务地址的注册和查找,相当于一个目录服务。服务提供者和消费者只在启动时与注册中心交互。注册中心不转发请求,监控中心负责业务统计,压力较小。调用次数、调用时间等,先在内存中汇总统计,每分钟发送一次给监控中心服务器,注册中心、服务提供者、服务消费者都是长连接,除了监控中心。通过长连接感知服务提供者的存在,如果服务提供者宕机,注册中心会立即推送事件通知消费者注册中心和监控中心全部宕机,不影响正在运行的提供者和消费者,消费者缓存在本地提供者列表注册中心和监控中心都是可选的。服务消费者可以直接连接到服务提供者。服务提供者是无国籍的。其中任何一个宕机后,不影响服务的使用。服务提供者全部宕机后,服务消费2.2Dubbo工作原理Dubbo工作原理自下而上分为十层,每一层都是单向依赖的。右边的黑色箭头代表层与层之间的连接。依赖,每一层都可以通过剥离上层来复用。其中Service和Config层是API,其他层是SPI。各层说明:第一层:服务层,接口层,第二层为服务提供者和消费者:配置层,配置层,主要是第三层为dubbo的各种配置:代理层,服务接口透明代理,生成服务clientStub和serverSkeleton第四层:注册层,服务注册层,负责服务注册和发现第五层:集群层,集群层,封装多个服务提供者的路由和负载均衡,将多个实例组合成一个服务第六层:监控层,监控层,监控rpc接口的调用次数和调用时间第七层:协议层,远程调用层,封装rpc调用第八层:交换层,信息交换层,封装请求响应方式,同步到异步第九层:传输层,网络传输层,将mina和netty抽象为统一接口层10:序列化层,数据序列化层。网络传输需求。三、Dubbo的负载均衡策略3.1首先解释一下什么是负载均衡。首先,让我们给出官方解释。维基百科对负载均衡的定义:负载均衡改进了工作负载在多个计算资源(例如计算机、计算机集群、网络链路、中央处理器或磁盘驱动器)之间的分布。负载平衡旨在优化资源使用并最大化吞吐量负载、最小化响应时间并避免使任何单个资源过载。使用具有负载平衡的多个组件而不是单个组件可以通过冗余提高可靠性和可用性。负载平衡通常涉及专用软件或硬件。不好理解,我通俗的告诉你。比如我们系统中的某个服务,访问量特别大。我们在多台服务器上部署此服务。当一个客户端发起一个请求时,有多少所有的服务器可以处理这个请求。那么,如何正确选择处理请求的服务器就很重要了。如果需要一台服务器来处理对服务的请求,那么将服务部署在多台服务器上的意义就不复存在了。负载均衡是为了防止单个服务器响应同一个请求,容易造成服务器宕机、崩溃等问题。从负载均衡这四个字我们可以很清楚的感受到它的含义。3.2看一下Dubbo提供的负载均衡策略Dubbo提供了多种均衡策略用于集群负载均衡。默认是随机随机调用。可以自行扩展负载均衡策略,参见:负载均衡扩展。备注:以下图片来自:尚硅谷2018Dubbo视频。3.2.1RandomLoadBalance(默认,基于权重的随机负载均衡机制)是随机的,根据权重设置随机概率。一个section的碰撞概率高,但是调用量越大,分布越均匀,使用概率后权重也越均匀,有利于动态调整provider权重。基于权值的随机负载均衡机制3.2.2RoundRobinLoadBalance(不推荐,基于权值的round-robin负载均衡机制)round-robin,按照约定后的权值设置round-robin比例。有一个慢provider积累请求的问题,比如:第二台机器很慢,但是没有挂掉,当请求转到第二台机器的时候卡在那里。久而久之,所有的请求都卡在了第二台机器上。基于权重的RoundRobin负载均衡机制3.2.3LeastActiveLoadBalance最小活跃调用数,相同的活跃数是随机的,活跃数是指调用前后的计数差值。让慢的提供者接收更少的请求,因为对于慢的提供者来说,调用前后的计数差异会更大。3.2.4ConsistentHashLoadBalanceConsistentHash,相同参数的请求总是发送给同一个provider。(如果你需要的不是随机负载均衡,而是一种类型的所有请求都到一个节点,那就用这种一致性哈希策略。)当某个provider挂了,原来发给provider的请求是基于虚拟Nodes的,共享给其他提供者,不会引起剧烈变化。算法可以参考:http://en.wikipedia.org/wiki/Consistent_hashing。默认情况下,只使用第一个参数Hash。如需修改,请默认配置160个虚拟节点。如需修改,请配置3.3配置方式xml配置方式服务端服务级别客户端服务级别服务端方式级别客户端方式级别注解配置方式:消费者基于注解服务级别配置方式:四zookeeperdowntime和dubbodirect连接情况zookeeperdowntime和dubbo直接连接面试中的情况可能会经常被问到,所以要注意。在实际生产中,如果zookeeper注册中心宕机,服务消费者在一段时间内仍然可以调用提供者的服务。实际上,它使用本地缓存进行通信,只是对dubbo健壮性的一种撤退。dubbo的健壮性能:监控中心宕机不影响使用,只是部分采样数据丢失。数据库宕机后,注册中心仍然可以通过缓存提供服务列表查询,但不能注册新的服务。注册中心点对点集群,任何一个down掉故障后,会自动切换到另一个注册中心。全部失败后,服务提供者和服务消费者仍然可以通过本地缓存进行通信。服务提供者是无状态的。崩溃后,服务消费者应用将不可用,无限重连等待服务提供者恢复。前面我们提到:注册中心负责服务地址的注册和查找,相当于一个目录服务。服务提供者和消费者只需要在启动时与注册中心交互,注册中心不转发请求,压力更小。因此,我们完全可以绕过注册中心——使用dubbo直连,即在服务消费者上配置服务提供者的位置信息。
