【分布式微服务专题】从单体到分布式(三、SpringCloud整合Dubbo)

前言

本片笔记主要是记录我整合Dubbo的过程。引入Dubbo主要是为了实现微服务之间的调用,即:RPC(Remote-Process-Call,远程过程调用)。
本次整合Dubbo可谓是曲折坎坷,耗费了不少时间和精力。不过也是收获挺多的,有些项目问题,真的不亲身经历,终是【纸上谈兵】。
举个鲜明的例子:我为什么要自己从0开始搭建微服务项目?因为我想要获得【从0开始搭建项目】的经验和能力!
整合至今,我至少学会了:

  1. maven的基本知识

不开玩笑,虽然maven一直在使用,但是我不是很理解compile/package/install都有什么用,只知道一直都是maven clean/maven install的用。那时候只想能简单使用就好了,其他我都不想管

  1. 理解、认识了SpringBoot、SpringCloud、SpringCloud Alibaba之间的关系

虽然一直在SpringBoot框架上写代码,但是我确实对【如何从0搭建一个SpringBoot】项目,没有一个很清晰的概念。现在不敢说有很深刻的认知,但是基本能从0开始搭建了

然后在整合Dubbo的时候,在学习Dubbo期间也遭遇了不少困难,也丰富了一些实操经验。如下:

  1. 学习Dubbo期间发现,Dubbo其实是跟SpringCloud同属于一个层级的东西,我之前一直以为它只是一个RPC框架。换句话说,Dubbo可以认为跟Spring Cloud 一样,是一个抽象的分布式微服务解决方案。官方介绍传送门:Dubbo与 gRPC、Spring Cloud、Istio 的关系
    在这里插入图片描述
  2. 重构项目结构

项目从单体,再到拆分出各个服务,若是拆分的不好,容易造成冗余依赖,以及模块之间的高度耦合。所以我在升级的过程中,也是尽可能地让项目更规范。这是一种软实力,内功心法

阅读对象

阅读导航

系列上一篇文章:《【分布式微服务专题】从单体到分布式(二、SpringCloud整合Nacos)
系列下一篇文章:《【分布式微服务专题】从单体到分布式(四、SpringCloud整合Sentinel)

前置知识

一、什么是Dubbo

Dubbo官方介绍传送门:传送门

1.1 基本介绍

Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题。用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力, 利用 Dubbo 提供的丰富服务治理特性,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。Dubbo 被设计为高度可扩展,用户可以方便的实现流量拦截、选址的各种定制逻辑。

1.2 设计目的

Apache Dubbo 最初是为了解决阿里巴巴内部的微服务架构问题而设计并开发的,在十多年的时间里,它在阿里巴巴公司内部的很多业务系统得到了非常广泛的应用。

Dubbo 被证实能很好的满足企业的大规模微服务实践,并且能有效降低微服务建设的开发与管理成本,不论是阿里巴巴还是工商银行、中国平安、携程、海尔等社区用户,它们都通过多年的大规模生产环境流量对 Dubbo 的稳定性与性能进行了充分验证。

阿里的东西是值得信赖的。毕竟,这些东西都经过了【巅峰双十一】超高并发考验的。

1.3 为什么需要 Dubbo,它能做什么?

按照微服务架构的定义,采用它的组织能够很好的提高业务迭代效率与系统稳定性,但前提是要先能保证微服务按照期望的方式运行,要做到这一点需要解决服务拆分与定义、数据通信、地址发现、流量管理、数据一致性、系统容错能力等一系列问题。
Dubbo 可以帮助解决如下微服务实践问题:

  • 微服务编程范式和工具
    Dubbo 支持基于 IDL 或语言特定方式的服务定义,提供多种形式的服务调用形式(如同步、异步、流式等)

  • 高性能的 RPC 通信
    Dubbo 帮助解决微服务组件之间的通信问题,提供了基于 HTTP、HTTP/2、TCP 等的多种高性能通信协议实现,并支持序列化协议扩展,在实现上解决网络连接管理、数据传输等基础问题。

  • 微服务监控与治理
    Dubbo 官方提供的服务发现、动态配置、负载均衡、流量路由等基础组件可以很好的帮助解决微服务基础实践的问题。除此之外,您还可以用 Admin 控制台监控微服务状态,通过周边生态完成限流降级、数据一致性、链路追踪等能力。

  • 部署在多种环境
    Dubbo 服务可以直接部署在容器、Kubernetes、Service Mesh等多种架构下。

  • 活跃的社区
    Dubbo 项目托管在 Apache 社区,有来自国际、国内的活跃贡献者维护着超 10 个生态项目,贡献者包括来自海外、阿里巴巴、工商银行、携程、蚂蚁、腾讯等知名企业技术专家,确保 Dubbo 及时解决项目缺陷、需求及安全漏洞,跟进业界最新技术发展趋势。

  • 庞大的用户群体
    Dubbo3 已在阿里巴巴成功落地,实现了对老版本 HSF2 框架全面升级,成为阿里集团面向云原生时代的统一服务框架底座,庞大的用户群体是 Dubbo 保持稳定性、需求来源、先进性的基础。

不过,在我的项目整合过程中,实际上我只是使用到了它的RPC能力。

笔记正文

当前项目框架:SpringBoot + MybatisPlus + SpringCloudAlibaba + Dubbo
改造前的项目结构如下:
在这里插入图片描述

一、整合Dubbo

我在整合的过程中,主要是参考了官方给的这2个示例:

另外,必须要理解Dubbo的一些核心概念。传送门:了解 Dubbo 核心概念和架构

1.1 改造项目结构

为了方便在后面的开发中降低模块间的耦合,以及项目代码结构更整洁好看,我把项目结构又做了一次简单的重构。如下图所示:

下面这种多模块结构,我认为大家都可以在以后的代码设计中借鉴,无论是单体还是微服务架构。我也是抄的Snowy开源框架的

在这里插入图片描述
我先简单介绍一下上面的包模块。

├── shenadmin       					// 整个服务的顶级父项目
	├── shen-common						// 项目公共模块
	├── shen-dependencies				// 项目依赖模块
	├── shen-provider-apis				// 项目对外暴露接口apis列表。provider直译:供应商
		├── shen-order-provider-api				// 订单服-对外暴露接口apis列表
		├── shen-product-provider-api			// 商品服-对外暴露接口apis列表
		├── shen-user-provider-api				// 用户服-对外暴露接口apis列表
		├── shen-wallet-provider-api			// 钱包服-对外暴露接口apis列表
	└── shen-servers					// 项目微服务列表
		└── shen-product						// 商品服
		└── shen-order							// 订单服
		└── shen-user							// 用户服
		└── shen-wallet							// 钱包服

特别声明:

为什么要设计shen-provider-apis?
之所以设计shen-provider-apis并在里面分服务定义了模块级xxx-provider-api,其实是遵循一种规范,这种规范主张【服务之间互相调用仅允许通过引用对方的xxx-provider-api模块,禁止直接将对方的模块直接引用】。
举个例子:shen-order订单服,想要使用shen-user用户服的接口,不能直接在shen-order下面依赖shen-user,而是通过引用shen-user-provider-api来间接实现。

那这样做有什么好处呢?

  1. 避免循环依赖。除了订单服会依赖用户服,有时候用户服可能也会依赖订单服,倘若使用直接依赖对方模块的方式,就会出现循环依赖
  2. 降低模块间的耦合,需要哪个模块的服务就引用那个模块的服务,减少冗余依赖

这个说法是相对的。在没有这种设计的情况下,很多用户会把对外暴露接口声明在类似shen-common的公共包里面,这样相对来说就比较多冗余项了

1.2 添加Maven依赖

引入Dubbo,需要先在顶级父项目shenadmin的pom中添加如下依赖管理:

<dependencyManagement>
        <dependencies>
            <!-- Dubbo -->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-bom</artifactId>
                <version>${dubbo.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

dubbo-bom,跟SpringBoot的spring-boot-dependencies是一样含义的东西。至于为什么要在父项目的pom中声明,为什么使用<dependencyManagement>包裹起来,我想大家应该知道吧?

bom,直译是:物料清单。dubbo-bom,即:dubbo项目的物料清单

然后,在所有微服务项目中,引入依赖:

        <!-- dubbo-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>

1.3 定义服务接口

服务接口,是Dubbo中沟通消费端和服务端的桥梁。看到最后你就知道这句话的含金量了

为了方便演示,我给每个服务都声明了一个【根据主键获取数据】的对外服务接口,当然是声明在对应的shen-xxx-provider-api下。如下所示:
在这里插入图片描述

至于里面的result包,则是用来声明我需要提供给外部的POJO定义,我们不应该直接把entity给暴露出去吧。

1.4 定义服务端的实现(@DubboService)

在上面定义了服务接口之后,我们需要在服务端这一侧定义对应的实现。这部分的实现相对于消费端来说是远端的实现,本地是没有相关的实现信息的。实现如下:(WalletApi
在这里插入图片描述

为了方便演示,我又新增了一个根据用户id获取可用余额的接口

在该WalletDubboProvider中,实现了WalletApi接口的getByWalletId方法,并且返回id对应的信息。

上面的walletConvertor是一个我自定义的、实现自MapStruct的POJO转换工具类,你可以理解为更高性能的BeanUtil。详细使用,自行百度【SpringBoot整合MapStruct】,本站CSDN也有一大堆教程

最最最重要的是,在WalletDubboProvider类中添加了@DubboService注解,通过这个配置可以基于 Spring Boot 去发布 Dubbo 服务

1.5 设置服务端配置

配置shen-wallet,如下:

dubbo:
  application:
    name: shen-wallet
#    qos-accept-foreign-ip: false
    qos-port: 30031
  protocol:
    name: dubbo
    port: 20031
  registry:
  	# 这个需要额外定义,默认的元组会跟SpringCloud元组冲突,虽然没问题,但是会报错,很恶心
    group: dubbo-dev
    address: nacos://localhost:8848
    #parameters:
    #  -register-consumer-url: true
  # 不检查消费者是否存在,默认true。默认情况下,如果发现依赖的服务不存在,会启动失败
  consumer:
    check: false

在这个配置文件中,定义了 Dubbo 的应用名、Dubbo 协议信息、Dubbo 使用的注册中心地址。

上面有个我认为比较不显眼、但是重要的配置,即:dubbo.consumer.check。这个配置表示:启动时检查提供者是否存在,true报错,false忽略。报错时会直接导致服务启动失败。所以,我喜欢关掉这个配置

注意,官方整合示例使用的是zookeeper充当的配置中心,不过也额外提供了Nacos整合方案,我在最开始也给出了。
另外大家是不是觉得dubbo.application.name这个玩意怪怪的,跟spring.application.name一样一样的。事实上,我们在开发中也是将这两个属性设置成一样的,前者是Dubbo自己的定义,做服务映射的时候会用到。怎么理解?简单来说就是,Dubbo服务启动之后,会向注册中心Nacos注册一个Provider配置文件,如下所示:
在这里插入图片描述
在这里插入图片描述

1.6 定义消费端的引用(@DubboReference)

我在shen-user用户服务这里,新增了一个【获取用户可用余额】的接口,如下:
在这里插入图片描述
具体实现:
在这里插入图片描述
UserDomian类中,通过@DubboReference从 Dubbo 获取了一个 WalletApi的RPC 订阅,这个walletApi可以像本地调用一样直接调用

当然,也不能漏了pom的依赖:

  <dependencies>
        <dependency>
            <groupId>com.shen.alicloud</groupId>
            <artifactId>shen-wallet-provider-api</artifactId>
        </dependency>
    </dependencies>

1.7 设置消费端配置

目前是同【1.5 设置服务端配置】一样。
说实在到目前为止,我不知道服务端跟消费端是否都一样配置。在官方的定义中,分为消费端(Consumer)和服务端(Provider),但是在我的实际场景中,服务是存在互相调用的,即存在:服务既是消费者也是提供者的场景。
不过我也没有做过多的配置,目前是能够互相调用使用的。

1.8 配置启动类(@EnableDubbo)

在所有微服务的启动类,添加以下注解:
在这里插入图片描述

1.9 测试

接着就可以通过访问上面用户服务的接口http://localhost:9021/user/sumUserAvailableBalance即可。

1.10 Nacos截图

再附上一张我当前Nacos上,配置列表和服务监控列表截图。

配置列表:
在这里插入图片描述
在这里插入图片描述

服务监控列表:
在这里插入图片描述
在这里插入图片描述

二、部分特性使用

到了这里,整合是整合完了,但我总感觉还是差点意思。
首先这在分布式微服务体系里面肯定是不够健壮的。一个最明显的例子是:我发现一旦某个服务不可用,那么,在服务调用过程中会报错500,这显然不是我想要的结果。所以,这里应该需要一个【限流/熔断】机制的存在。
当然,需要的不止于此,我还在研究中。

顺便给大家提一嘴,Dubbo提供了【学习任务】,让我们可以跟着任务学习Dubbo的各种特性,感兴趣的朋友可以跟着学习一下。而且提供到都是微服务里面,一些比较典型的场景。
Dubbo学习任务传送门

2.0 说在前面

2.0.1 官方配置

一些常规的配置,大家看这个就行了,我这里就不多提了。官方配置解释传送门

*2.0.2 Dubbo Admin

另外,Dubbo提供了一个简易的,自己的【服务治理】可视化后台项目Dubbo Admin。Admin 控制台提供了 Dubbo 集群的可视化视图,通过 Admin 你可以完成集群的几乎所有管控工作。

  • 查询服务、应用或机器状态
  • 创建项目、服务测试、文档管理等
  • 查看集群实时流量、定位异常问题等
  • 流量比例分发、参数路由等流量管控规则下发

关于相关操作配置使用官方介绍,点此传送门:Admin 控制台操作手册

2.1 超时与重试

什么是超时与重试我就不解释了。不过有一点我觉得很有意思的是,通常我们的超时跟重试的规则配置,都是静态的,也就是说一旦设置了想要更改,需要重启服务。而Dubbo除了静态,还支持动态修改,这一点我觉得很重要!
不过动态修改,需要使用Dubbo Admin管理后台,目前咱不知道是否有其他动态修改手段。

静态修改方式,可以在配置文件中修改,也可以在@DubboReference上设置:
在这里插入图片描述

@DubboReference(timeout = 3000, retries = 3)

2.2 负载均衡

关于负载均衡,官方介绍传送门:负载均衡传送门

关于负载均衡,根据官方的说法,如果我们什么都不设置,默认使用的负载均衡策略是加权随机策略(loadbalance=random)
而且有意思的是,Dubbo给我们提供的负载均衡策略,有【基于服务端的】和【基于客户端】的,甚至能精细到方法级别的负载均衡。整体来说比较简单,我就不写示例了。感兴趣的朋友点击上面的传送门,看看官网的示例吧。

消费端:

@DubboReference(loadbalance = "random")

服务端:

@DubboService(loadbalance = "random")

2.3 限流&熔断

关于限流&熔断,官方介绍传送门:限流&熔断传送门

【限流&熔断】一直都是微服务领域里面一个比较经典的话题。他们的全称其实是指:流量控制、熔断降级。在这里,我只是简单说一下概念,具体的信息还要大家去官网看看吧。

2.3.1 流量控制

流量控制更多的是站在 Dubbo 服务提供者视角来保证服务稳定性,通过明确的为 Dubbo 服务设置请求上限阈值,确保服务所处理的请求数始终在一个合理范围之内,从而确保系统整体的稳定性。
在这里插入图片描述
根据服务的具体部署情况,服务所能处理的流量上限是一定的,当对服务的请求数量保持在合理的范围时,系统运行正常;而当请求数量严重超过服务处理能力时,如大促期间的流量洪峰等场景,就可能造成服务提供者端的资源过度消耗、负载过高,进而出现响应延迟、请求无应答、系统假死等情况。
流量控制解决的问题和工作方式比较容易理解,真正的难点反而是:如何确定服务所能处理的流量最大值。所以,根据这种特点,Dubbo提供的流量控制解决方案,通常如下:

  • 方案一:是由用户预先设定一个固定的限流值,如 Dubbo 通过集成 Sentinel 等产品实现的限流能力即是这种模式
  • 方案二:Dubbo 框架自动根据系统或集群负载情况执行限流,相比用户预先设置限流值更加灵活方便,Dubbo 目前内置了自适应限流模式
2.3.2 熔断降级

熔断降级则是更多的从 Dubbo 服务消费者视角来保障系统稳定性的重要手段。一个服务往往需要调用更多的下游 Dubbo 服务来完成业务逻辑,这时下游服务的稳定性就会影响当前服务甚至整个系统的稳定性,熔断(Circuit Breaking)即是面向不稳定服务场景设计的,它能最大限度避免下游服务不稳定对上游服务带来的影响。
在这里插入图片描述
如上图所示,Dubbo Consumer 依赖的下游的三个 Dubbo 服务,当 Service 3 出现不稳定的情况时(如响应时间变长、错误率增加等),从而 Consumer 调用 Service 3 的线程等资源就会产生堆积,如果此时我们不在 Consumer 侧做任何限制,则 Service 1 与 Service 2 的调用都会受到稳定性影响。通过熔断 Service 3 我们就能保证整个 Dubbo Consumer 服务的稳定性,不拖垮整个 Consumer 服务,熔断 Service 3 的方式可以有很多种实现,包括线程数、信号量、错误率等。

Dubbo 通过集成业界主流的框架实现了服务熔断降级能力:SentinelHystrixResilience4J

2.3.3 总结

流量控制更多的是站在 Dubbo 服务提供者视角来保证服务稳定性
熔断降级则是更多的从 Dubbo 服务消费者视角来保障系统稳定性的重要手段

2.3.4 使用示例

通过学习,我发现,【流量控制】跟【熔断降级】都是可以通过Sentinal(服务治理组件)实现的,而且,这也是Alibaba解决方案推荐的组件。所以我的想法是,下一篇笔记就做【Sentinal的整合】了。
所以,大家可以关注我下一篇笔记咯。(如果我没在这里贴传送门,那就是我还没整合完,在学习中)

2.5 服务分版本(多版本管理)

关于【服务分版本】官方传送门:服务分版本官方传送门

什么是【服务分版本】?看看它特性说明你就知道了。
在这里插入图片描述
他有什么使用场景呢?官方说法:当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用
换句话说:灰度发布。

使用方式也比较简单,就是在@DubboService@DubboReference中设置version就好了。

@DubboService(version = "1.0.1")
@DubboReference(version = "1.0.1")

或者,是在配置文件中设置也可以。
在这里插入图片描述

2.6 切换序列化框架

在Dubbo中,我们可以切换序列化框架。当然,关于序列化框架的选择,如果不理解可以交由Dubbo帮你决定,Dubbo目前默认的是hessian2
目前Dubbo支持的序列化框架有:Hessian2、Fastjson2、Protobuf、Protostuff、FST、Kryo等。

说来真的是坑,为了实验,我尝试整合Kryo跟protobuff,硬是搞了我一天也没整出来,主要是一些jar包一直下载不了,再然后终于下载了,结果存在兼容问题(百度有人说是兼容问题)。后来使用protostuff终于可以了

整合示例:
1)添加pom依赖(注意版本,我用的1.0.3,dubbo版本是3.2.0.beta3)

        <dependency>
            <groupId>org.apache.dubbo.extensions</groupId>
            <artifactId>dubbo-serialization-protostuff</artifactId>
        </dependency>

2)设置配置文件
在这里插入图片描述
这样就可以了。我上面的配置文件的意思是:倾向于选择protostuff,如果没有则使用hessian2(兜底)。

三、吐槽

Y1S1,Dubbo的文档真的… 一言难尽,敷衍不说,很多相同内容,不同导航模块,相同内容配置可能不一样,我怀疑是多人一起写的。
Dubbo在介绍的时候也是很有B数的,知道自己劣势,但是它不改啊… 我的天啊!(下图是Dubbo官方文档的自我介绍,我没污蔑它)
在这里插入图片描述

四、下一步

下一步,我打算整合Sentinal到项目中

学习总结

  1. 学习了Dubbo一些基础知识
  2. 构建了一套基于Dubbo协议的RPC服务调用

感谢

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

验证码有毒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值