飞道的博客

Dubbo基础专题——第一章(带你认识Dubbo)

318人阅读  评论(0)

前言:刚完成的Spring基础专题本想更新源码的,但是发现分布式非常火,而我喜欢玩这个,所以今年我希望把我的知识可以分享给正在奋斗中的互联网开发人员,以及未来想往架构师上走的道友们我们一起进步,从一个互联网职场小白到一个沪漂湿人,一路让我知道分享是一件多么重要的事情,总之不对的地方,多多指出,我们一起徜徉代码的海洋!
 
我这里做每个章节去说的前提,不是一定很标准的套用一些官方名词,目的是为了让大家可以理解更加清楚,如果形容的不恰当,可以留言出来,万分感激!

1、基础知识

1.1、分布式基础理论

互联网业内,不少人口中经常喜欢说,分布式系统,CAP理论,包括大厂中对于面试,实战,都会注重这方面的筛选,考核。那本章开始,真正带你走进分布式的世界,为什么要有分布式的存在,和我们目前主流的微服务之间,又有什么关系呢?

我先引经据典《分布式系统原理与范型》对于分布式的定义:

分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统。

首先,是若干个独立计算机,其次,对于用户来说,他在使用这个系统,就感觉像单个完整系统一样正常运行!

比如我们在用京东商城完成了你的购物需求,对于你来说你体验到了一个完整的京东商城系统,实际上京东商城后台有成千上万台独立的计算机,为我们提供服务,而这些计算机或者服务器,完整的构成了一整个京东商城系统!

为什么要有分布式系统呢?

实际上随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,于是想着,这么多的功能,模块,我是不是都可以单独拆出去作为一台计算机,去独立的提供自己的服务?通过服务之间的调用关系,是不是也可以用某些技术手段,来

进行统一的维护,治理这些偌大的服务模块呢?于是诞生了很多主流框架,比如本章的Dubbo,还有SpringCloud生态体系,SpringCloud Alibaba体系。所以分布式服务架构以及流动计算架构一定是当下的主流,亟需一个治理系统确保架构有条不紊的演进和

迭代发展!

1.2、发展的演变

上面我们提到垂直应用架构,这里我带你看看发展过程。

我先截个完整的发展图,再和你细分下过程!这张图来自Dubbo的官网,感兴趣可以看看。但是我觉得你一定不会去看官网的!

最开始,网站很小的时候,只需一个应用,就可以将所有功能(比如订单,商品,支付,用户,搜索等)都部署在一台服务器上,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键——形成单体应用架构

这个时候流量是没这么多的,而且这个产品也不大,互联网这个噱头早期的时候发展不明显,用户量非常小,单一的单体应用架构足以满足需求。

但是随着用户量增大,需求不断增加,要有更多的人来迭代这个产品,发展这个系统,从一个阿里的单体淘宝,再牛逼的服务器,一台肯定扛不住啊,那有人说搞多台(水平应用架构),就是一台A上面部署一整个完整的系统,A撑不住了,那就复制出来成为

B,B和A一毛一样,也是具有所有的功能模块,好了可以解决一些压力了,但是我今天要开始更新功能了,首先把A服务要停掉,更新个包上去,我只修改了订单功能,但是我整个项目要停了重启,也就意味着这段时间用户用不了,接着A好了,再替换B,替

换C等等,还有一点,你开发,我也开发,你开发商品,我开发订单,我要等你开发完了我的功能才能一起打包部署,极大的浪费彼此的时间,很多小公司会有“捆绑式加班”,你功能完了之后,等我写完了一起测,没问题了,你再走,哈哈!~

马总开始觉得,这个用户上来的话,开始扛不住了,成本啥的很高啊,离职率也....

缺点也暴露出来:

  • 功能扩展比较难,单体的项目会越来越大,从几百兆会到几个G...
  • 性能无法保证,一个几十兆的项目到几百兆甚至上G,你说启动要多久?一台服务器再好跑你的系统,cpu内存io,也扛不住啊。
  • 协同开发问题,我开发好了,凭啥不能下班回家,非要等你写完一起打包测?
  • 不利于升级维护,一个一个停服务,启服务,运维每次加班都是干这个事情,用户一会可以用,一会用不了,开发头发都干秃了...

于是演变成了垂直应用架构

访问量逐渐增大,单一应用增加机器带来的加速度会越来越小,这个时候,马爸爸要告诉下面的大牛们,你们要改下,这撑不住啊,于是大佬们开始将应用拆成互不相干的几个应用,分别部署在不同的服务器上,以提升效率。此时,用于加速前端页面开发的

Web框架(MVC)是关键。

订单拆出去,在一台服务器上,用户系统拆出去,也在一台服务器上,商品系统也是一样拆出去。所以这个称为垂直应用架构。

这个时候解决了单体,水平的局限性,如果订单访问量比较大,我可以把订单服务抽出来单独用一台服务器跑,或者多搞几台也是一样。对于用户系统,也是高频率使用,用户系统我也多做几台服务器,对于一些使用量不大的服务,那么我可以用很少的服务

器,来支撑这个服务的运行!!

所以上面的问题基本都可以得到比较好的解决:

  • 功能扩展,没啥单体,拆这么多的服务,再大也大不过一个单体啊,不行我再拆
  • 性能问题,我跑的好好的,出问题也是我的,和你没关系,你性能问题可以得到保证,我也可以加机器等方式维持我的性能稳定,不影响你
  • 协同开发,你开发你的,我开发我的,在不同的服务器上,咱俩不相干。
  • 升级维护,你升级你的呗,我后面升级,你只要不要用到我紧密的功能必须要我更新的。

优点很明显:通过切分业务来实现各个模块独立部署,降低了维护和部署的难度,团队各司其职更易管理,性能扩展也更方便,更有针对性了。

但是你看起来,乖乖没缺点了,是真的吗?

你的模块有公共的代码,我的也有,项目越来越大,公共的东西会越来越多,抽不出来吧?比如基本的代码,你要写两套,甚至每个服务都可能要手写重复代码去实现一遍又一遍。

这就是公用模块无法重复利用,开发性的浪费!

还有,当垂直应用越来越多的时候,应用之间前后端的频繁的交互不可避免,那很多代码,都是一毛一样的,甚至我用户的界面万年不改一次,但是我每个服务里都有这个代码,能不能将核心业务,或者公共的抽取出来,作为独立的服务,逐渐形成稳定的服

务中心,使前端后端应用能更快速的响应多变的市场需求。于是衍生出来了分布式服务架构,用于提高业务复用及整合的分布式服务框架(RPC)是关键,这里提到RPC,后面我详细介绍。

这个时候,减少了很多公共的服务,分离了前后端调用逻辑,比如提供用户注册,登录,验证等这些服务,去拆出来,独立部署,而不是像垂直应用那样,前后端放一台上,进程内互相调用,且每个模块都有用户注册功能,校验,以及很多基础的服务,

而垂直架构每个独立的服务,都要运行个用户注册,登录校验,基础服务,这代码太冗余了没必要,所以,到这个架构上,其实解决了不少的问题,公共抽出来单独运行了,前后端在不同的服务器上,调用方式也改变成远程调用方式了,万年不改的公共前端

也不至于每次服务他都要404一段时间,起码职责更加单一,相对独立化,和公共抽出单独维护。

 

可是你想想这些服务之间,调用会不会很频繁啊~ 如果我有几台服务挂了你怎么知道我挂了? 你请求不到,到底是你的问题,还是网络拥塞,还是我的服务不健康了?会不会把你给拖垮?那这么多的应用在里面,你怎么更好的监控和维护呢?节点故障,容错

率要很高,不会导致一个完蛋,拖垮所有系统?等等这些问题都是要考虑的!

进而衍生出流动计算架构

当服务越来越多,容量的评估,小服务资源的浪费,调用频繁会不会拖垮其他服务,流量大的服务能不能实现自动的加服务器扩容,等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的

资源调度和治理中心(SOA)[ Service Oriented Architecture]是关键。

所以互联网的整体架构发展,目前就是这样的情况,下面我们来唠叨下,我们讲的RPC是什么鬼玩意,和Dubbo又有什么关系呢?

 

2、RPC介绍

什么是RPC?

引经据典:RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数(可以理解为接口),而不用程序员显式编码这

个远程调用的细节。即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。

很简单,比如我有个UserService用户服务接口,要调用getOrder获取订单的方法,getOrder这个方法在OrderService这个接口中,也就是要调用OrderService这个接口的实现类嘛,如果OrderService这个代码在我的UserService同项目下,都有各自的实现

类,UserServiceImpl和OrderServiceImpl,怎么写调用? 是不是写private OrderService orderService; 然后orderService.getOrder()就可以了?当然@Autowired类似的注解不能省略,那这个是在一台服务器中的一个应用的代码这么写,好了,我把订单抽出去

了!!抽到另一个服务器上,单独一个服务在跑了,哎,但是我可以保证你的代码UserServiceImpl调用OrderServiceImpl的getOrder这些代码,保持不动,只要做某些额外的事情,甚至只要一个注解的方式,就能让你觉得,这个调用方式,代码上,和之前在

一台服务器上运行,没有任何区别!!!

这就是所谓的RPC技术。讲的通透吗?

RPC基本原理:

实际上就是client和server之间,架起一个网络连接,client把信息通过socket传输到server端,然后server端返回数据给client端,很简单的流程,英文看不懂就看字吧,但是其实核心的东西,远远不止我讲的这些。stub你理解为小助手

举个例子:

客户端client有个helloA方法,要调用server端的helloB方法,先是client发请求给小助手,小助手开始建立连接socket,建立成功后,发送序列化的请求,包括参数等,网络传输,server端的B小助手,拿到了这个序列化请求,先反序列化看你带什么东西过来,

于是调用B的本地化,server开始处理,然后返回给B的小助手serverStub,再序列化回去,给到A的小助手,A小助手反序列化后,最终A的client拿到结果!

所以这就是RPC调用过程,一个好的RPC框架机制有两点

  • 建立连接的过程快不快?(通信效率)
  • 序列化和反序列的机制速度快不快?(序列化和反序列化效率)

市面上有很多RPC框架,比如Dubbo,GRPC,Thrift,HSF(淘宝的 High Speed Service Framework)——当年两个顶尖团队一个Dubbo,一个HSF团队(最终淘宝架构选择),干仗,结果Dubbo团队没干过,就解散了,所以Dubbo开始流行在各个互联网

公司。

而接下来我就要讲下Dubbo这个高性能的RPC框架!!

 

3、Dubbo是什么

讲Dubbo之前我给大家普及一个有趣的故事吧?

Dubbo是阿里巴巴内部使用的分布式业务框架,2012由阿里巴巴开源,很多公司开始使用Dubbo,据说当年淘宝要换架构,两个团队一个HSF,一个Dubbo团队,为了换架构的事情一直在争论,而最终淘系决定了选择HSF,这里澄清下,不是阿里主推,原因

是HSF比Dubbo更早,而且是淘宝系统重大重构的时候,自然生成的,根植淘系的基因了,后面已经无法替换成其他技术了,不是技术原因,是成本太大,收益不高。两个团队当时也pk过一次,pk的结果是Dubbo的部分功能合并到HSF,所以此时Dubbo的业

务团队基本分流到其他团队里了,比如梁飞大佬,转到天猫团队了,分流后,Dubbo在阿里的维护程度很低,社区活跃度很低,当当网这个时候开始挖人,挖了一些Dubbo的贡献者去做了个Dubbox,支持Rest协议,因为Dubbo默认只支持是Rpc的嘛,此时国

内培养了一大批Dubbo程序员,虽然影响力在上升,但是维护低了,团队分流了。此时SpringCloud迅速抓住机会,开始流行起来,后来2017年后,阿里才重新捡起来重新定位,加上各大贡献者规划了3.0,拥抱ServiceMerch,19年开源给Apache去维护了。

插入这段历史,也是要了解下的~!

Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现

记住,Dubbo是RPC框架的典型代表,从官网上看(https://dubbo.apache.org/zh/),也是一套分布式服务的解决方案!

3.1、Dubbo六大核心能力

  • 面向接口代理的高性能RPC调用

Dubbo提供高性能的基于代理的远程调用能力,什么叫基于代理,就是我上面说的那个小助手Stub,服务以接口为粒度,为开发者屏蔽远程调用底层细节

  • 智能负载均衡

Dubbo内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量

  • 服务自动注册与发现

Dubbo支持多种注册中心服务,比如你可以使用Zookeeper,Nacos,服务实例上下线实时感知。

  • 高度可扩展能力

遵循微内核+插件的设计原则,所有核心能力如Protocol、Transport、Serialization被设计为扩展点,平等对待内置实现和第三方实现(这段话听听就好~)。

  • 运行期流量调度

内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布(100台我先升级10台,没问题再慢慢升级其他的),同机房优先等功能(这个你也听听就好,但是要知道一个灰度发布)。

  • 可视化的服务治理与运维

提供丰富服务治理、运维工具:随时查询服务元数据、服务健康状态及调用统计,实时下发路由策略、调整配置参数。

 

3.2、基本架构

我从官网copy的一个图过来

这是一个dubbo的架构基本组成部分,有这些:

  • Consumer服务消费者

调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

  • Provider服务提供者

暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。

  • Monitor监控中心

服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

  • Registry注册中心

注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

以上四个,就是Dubbo架构的组成部分,那么之间的调用关系是怎么样的呢?注册中心又是什么东西呢?

在没有dubbo的时候,我们一个服务,想要远程调用另一个服务的通信方式,可以使用RestTemplate,或者HttpClient,写死域名或者ip+端口+uri+参数,甚至你也可以通过nginx转发url做负载的方式分压,这个都没问题,但是此时我想问下,如果A调用B,B这

个时候资源满了,A调不通,你说你这个时候,觉得什么问题?网络拥塞?B挂了?B比较紧张但是没有挂,还活着,或者A服务资源紧张,这些排查下来估计也要大半天的时间没了,你无法很准确定位到问题,这是其一;其二,一旦B挂了,很有可能会拖垮

A,甚至其他服务,是不是开始重启大法?

服务一旦多起来,你是不是没法维护?这么多的调用关系,你无法合理的对这些服务进行管理和维护,甚至你想满足高可用场景,你都暂时不能保证,你怎么保证一台服务上线有问题,你想强迫下线?除非你一台一台去stop?kill进程?像这些问题,大一点的

企业,产品一大,无法维护。

此时有大佬想了个点子,为了更好的管理你们所有的服务,我要让你们先入驻到我的花名册里,这样你找我,很方便,甚至,我在不在线,你也知道,如果我有很多服务,你找到名字,就可以找到我所有注册的ip地址,就可以顺便调用我了,

而调用方式,谁说了算都可以,而这个花名册,就是注册中心,有了这个玩意,很多问题就可以随之演进,慢慢就出现了解决方案!

调用关系是怎么样?

1、首先,你写了个OrderService,里面有很多方法,都是关于订单的业务,此时假设你作为生产者,你的服务启动了,Dubbo会把你这个服务,注册到注册中心上提供出了自己的服务,好了,你在上面了,其他服务想来找你,问下保安要下入驻手册(注册中

心)就知道你在几楼了,不用费劲一个一个找;

2、此时,我写了UserService,里面是用户相关的业务,启动了,也帮我把我的服务注册上去了,而假如此刻我作为消费者,我要找生产者吧,我就要上注册中心,订阅我要消费的服务。问保安1103怎么走

3、然后,注册中心返回服务提供者地址列表给消费者,我就找到你了,假如你刚好搬到了1203,,注册中心将基于长连接推送变更数据给消费者,告诉你他现在的地方

4、服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。如果只有一台,就只调用这台就好了。

5、Monitor开始进行监控服务之间的关系,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心,保证服务的正常运行。

讲了很多理论,我们实战一波,我对着官网告诉你们怎么玩:

3.3、Dubbo环境搭建

先安装注册中心,这里我们用Dubbo推荐的Zookeeper,不熟悉的读者,就先把这个作为注册中心来学,来了解。(地址:https://dubbo.apache.org/zh/docs/v2.7/user/references/registry/

这里我环境是windows,选用注册中心版本是Zookeeper3.4.11,这个版本比较稳定,链接地址我发了:https://pan.baidu.com/s/1ZRsCHfn-C3-dnNEiSOlckA 提取码:ilc3 

复制这段内容后打开百度网盘手机App,操作更方便哦

解压到自己的目录下,然后进入bin目录,执行zkServer

cmd进去后直接zkServer回车,前提你先要本机配置好JAVA_HOME,不然会报错JAVA_HOME is not set,推荐1.8的jdk,然后你启动发现有个其他的报错出现

这个意思就是在conf下面找不到zoo.cfg这个文件,我们看下这conf目录下默认是没有这个文件的,只有zoo.example.cfg

所以我们要copy一个出来,重命名成zoo.cfg,内容暂时不变

然后发现启动成功了!端口是2181

看下这个配置文件的东西,这个dataDir数据文件存储的地方,默认是当前文件夹的/tmp/zookeeper,这个目录是没有的,所以我们和conf同级别,新建一个data目录,配置文件路径指向data

指向我们也改成了dataDir=../data

然后再重启下zk,就可以了!端口是2181

我们可以测试,也是在bin目录下打开cmd,执行zkCli.cmd

我这里就简写Zookeeper为zk了啊,其实zk我这里介绍下,是一个树形目录服务:详情https://dubbo.apache.org/zh/docs/v2.7/user/references/registry/zookeeper/

根节点是dubbo,然后下面一次是service,type,url这些节点都会存很多数据,这些我后面会告诉你具体意思,先知道zk这里用来做注册中心。

Zookeeper这里就安装好了~

然后我们安装个监控中心(其实可以不安装,不影响后面的操作,但是我还是想让你们看到效果)!一样是下载下来,是个jar包;我这边提供好了一起打包你们下载!

我们启动下jar包:java -jar dubbo-admin-0.0.1-SNAPSHOT,启动成功,访问localhost:7001就可以看到登录界面

账号密码默认是root

后面功能我们慢慢使用。这里要注意

这个控制台启动的前提,zk一定要启动,并且是2181端口,如果你熟悉了,后面可以改端口,目前不熟悉,先不要改!

如果是linux环境,那么百度看看就可以了,这个原理都是一样的!

还差生产者和消费者,假设我们有个需求:

某个电商系统,订单服务需要调用用户服务获取某个用户的所有地址;我们现在 需要创建两个服务模块进行测试 

模块

功能

订单服务web模块(消费者)

创建订单等

用户服务service模块(生产者)

查询用户地址等

订单服务web模块在A服务器,用户服务模块在B服务器,A可以远程调用B的功能

根据dubbo《服务化最佳实践》中提到:https://dubbo.apache.org/zh/docs/v2.7/user/best-practice/

建议将服务接口、服务模型、服务异常等均放在 API 包中,因为服务模型和异常也是 API 的一部分,这样做也符合分包原则:重用发布等价原则(REP),共同重用原则(CRP)。

如果需要,也可以考虑在 API 包中放置一份 Spring 的引用配置,这样使用方只需在 Spring 加载过程中引用此配置即可。配置建议放在模块的包目录下,以免冲突,如:com/alibaba/china/xxx/dubbo-reference.xml

服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,否则将面临分布式事务问题,Dubbo 暂未提供分布式事务支持。

服务接口建议以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸。不建议使用过于抽象的通用接口,如:Map query(Map),这样的接口没有明确语义,会给后期维护带来不便。

所以啰嗦了半天,意思就是好好整你的代码,该抽的抽,抽到恰当好处!

这是目前的方案,这一章有点多,下一章继续吧,有点困咯~~

下一章我们开始搭建Dubbo的服务开发环境,敬请订阅哈!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


转载:https://blog.csdn.net/qq_31821733/article/details/116175712
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场