1.RPC框架
在java的发展中,随着业务的越来越庞大,单体架构的工作繁琐且耦合度高,因此单体架构过渡到了分布式架构,而分布式架构就必然涉及到各个服务之间的远程通信(RPC框架),RPC框架如图所示:
工作流程:
a.客户端调用客户端Sub(client stub).这个调用是在本地
b.客户端stub会将要传输的参数进行包装,并通过系统调用发送到服务端机器。打包的过程就叫做序列化。(常见的方式有:XML、JSON、二进制编码)
c.客户端本地操作系统发送信息至服务器。(可通过自定义TCP协议或HTTP传输)
d.服务器系统将信息传送至服务端stub(server stub)
e.服务端stub(server stub)解析信息。该过程叫反序列化
f.服务端(server stub)调用程序,并通过类似的方法返回给客户端
这样来讲:我们调用远程服务,一是要遵守能够传输的消息格式,二是传输的方式,三是调用异常的怎么办。这些我们客户端都是不可行自行去管理的,交给RPC框架去处理;
RPC协议正是定义了这样的一种通信的标准规范,为了满足不同的场景需求,于是很多标准化的RPC框架就在这个协议的基础上产生了。
2.dubbo
dubbo就是在rpc协议的基础上诞生的,但是它不仅仅是一个RPC框架,更是一款微服务框架,为大规模微服务时间提供高性能RPC通信、流量治理、可观测性等解决方案。
思考: 我们讲了dubbo的由来,那么dubbo为什么能够被快速用起来呢? 肯定是解决了一些棘手的问题。
(1) 服务越来越多了,那是不是就说明服务调服务,服务链路越来越长了,如何对服务链路进行跟踪和监控呢?
(2)服务通信之间的异常,是否会牵一发而动全身呢?因此我们需要有一种保护机制防止一个节点故障引发大规模的系统故障,就是说要有容错机制
(3)服务的大规模集群之间是怎么互相发现互相感知的,因此需要有一个注册中心对服务进行集体管理
(4)服务的大规模集群请求量的分发需要引入负载均衡机制。
3.dubbo特性
dubbo有着一系列高性能的对上述问题的解决方案
a.面向接口代理的高性能RPC调用,服务以接口为粒度,屏蔽了远程调用底层细节
b.智能负载均衡,内置了多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量
c.服务自动注册与发现,支持多种注册中心服务,服务实例上下线实时感知
d.可视化的服务治理与运维,提供丰富的服务治理、运维工具。可以随时查询服务元数据、服务健康状况及调用统计,实时下发路由策略,调整配置参数
e.运行期流量调度,内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。
f.高度可扩展能力,遵循微内核+插件的设计原则,平等对待内置实现和第三方实现。
4.dubbo架构
Provider:暴露服务的服务提供方
Consumer:条用远程服务的服务消费方
Registry: 服务注册与发现的注册中心
Monitor: 统计服务的调用次数和调用时间的监控中心
Container: 服务运行容器
5.demo案例
假设我们有这样的一个简单的需求,需要查询当前用户还可以领取的优惠券列表。则基于dubbo的实现架构为分析: user为一个独立部署的服务,coupon也为一个独立部署的服务。
我们这样来学习dubbo协议,我们知道dubbo协议是一个远程网络通信框架,那么我们user服务如果想要调用到coupon服务,那么我们就需要在user服务中配置conpon服务提供的这个接口url地址才能够访问。这就是dubbo的点对点通信。
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="coupon-portal"/>
<!-- 使用multicast广播注册中心暴露服务地址 -->
<dubbo:registry address="N/A"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<!-- 声明需要暴露的服务接口 -->
<dubbo:reference
interface="zsc.com.cn.user.IUserService" id="userService"
url="dubbo://192.168.36.1:20881/zsc.com.cn.user.IUserService"/>
于是我们使用dubbo协议的这个需求的整个流程就是 前端访问--> REST接口->dubbo协议点对点访问user-api--->user api的实现类---> dubbo协议点对点访问coupon-api ---> coupon api的实现类-->再将结果返回。
思考: 我们的接口越来越多怎么办,如果服务是集群部署呢,我们的url也需要配置多个的吗?如何集体管理这么多个服务? 于是注册中心就派上了大用场,将这些接口都统一注册到注册中心中,其它服务如果引用,去注册中心上订阅即可。显然,从dubbo架构图中我们可以看出来,dubbo天然就支持服务注册与发现,目前dubbo能够支持的注册中心如consul,etcd,nacos,sofa,zookeeper,eureka,redis等已经很多了。
Springboot有着天生集成dubbo的优势,那么在springboot中如何使用dubbo;
a.首先引入jar包依赖
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-bom</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
spring-boot与dubbo的兼容包以及注册中心zookeeper包
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
b.在启动类上开启dubbo
c. dubbo的相关配置(在properties中进行配置)
# 应用名称
spring.application.name=coupon-service-provider
dubbo.application.name=coupon-service
# dubbo的协议 -1代表的是端口号随机生成
dubbo.protocol.port=-1
dubbo.protocol.name=dubbo
# 注册中心 配置中心 元数据中心 id为key
dubbo.registry.id=zk-registry
dubbo.registry.address=zookeeper://192.168.8.133:2181?timeout=20000
dubbo.config-center.address=zookeeper://192.168.8.133:2181?timeout=20000
dubbo.metadata-report.address=zookeeper://192.168.8.133:2181?timeout=20000
d. 服务怎么发布 增加@DubboService注解即可,就会自动进行扫描,并发布到注册中心
e. 服务怎么引用订阅 增加@DubboReference 注解即可,就会从注册中心中引用这个接口
分析: c中我们配置了3个中心地址,registry注册中心,接口服务url的存储,config-center 配置中心,这是dubbo的公共配置可以单独抽取出来(dubbo.properties),metadata 元数据中心,这是dubbo的url过于长的话,把url上携带的相关参数进行剥离开来。注册中心,元数据中心和配置中心都是可以单独部署的。