Dubbo 基础概念

RPC

分布式的必要性

当用户的数量增大,一个服务器不能解决过量的需求时,我们就需要使用多个服务器来满足大流量的数据访问。每个服务器部署不同的业务,如果某一个服务的访问量比较大的话也可以将这个服务同时部署在多台机器上

RPC 是什么

为了解决分布式系统直接可能会出现的相互调用,为了让多个服务器协调运行,我们也需要一个完整的规范来控制服务器

RPC 就是远程过程调用,它的作用是让不同服务器之间可以相互调用,让分布式或者微服务系统中不同服务之间的调用像本地调用一样简单

注意,RPC 是一种思想,RPC 框架是这个思想的具体实现

主要属性

影响 RPC 框架性能的主要属性有下面几个:

资源定位与服务发现:我们需要知道自己应该调用哪台主机的哪个方法,在其中可能出现的问题都需要解决,比如我们如何确保要调用的主机没有挂掉呢、我们这么找到需要调用的主机呢

传输协议:为了让不同服务器可以传输数据,选择一个合适的传输协议尤其重要,在合适的场景下可以选择 TCP、HTTP 等协议

序列化协议:java 中一切即对象,对象的传输需要序列化,可以使用 jdk 自带序列化方法或者 json 等来序列化对象

在这里插入图片描述
在服务器方法之下加了两层,一层用来序列化,一层用来传输数据,因此用户可以直接使用服务器方法调用另一个服务器方法

这张图片中:
1、5调用方法
2、7序列化
3、8网络数据传输
4、9解码
6、10返回结果

RPC 框架就是封装了2到9步,让用户可以直接使用1、10

你已经知道了 RPC 的大体步骤,快来手写一个RPC框架吧(

Dubbo 的优点

现在阿里为我们提供了一套优秀的 RPC 调用框架

1,提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用底层细节

2,智能负载均衡,内置多种负载均衡策略,显著减少调用延迟,提高系统吞吐量(负载均衡指的是,多台服务器提供同一种服务时,负载均衡会让每个服务器平均处理请求的数量)

3,服务自动注册,支持多种注册中心服务,服务实例上下线实时感知

4,可视化的服务治理与运维

依赖关系

在这里插入图片描述
registry:注册中心,生产者在这里注册服务,注册中心也会告诉消费者生产者是否宕机,一般使用zk做注册中心
provider:生产者,也就是处理业务的服务器
consumer:消费者,调用服务的服务器
monitor:监控中心

Dubbo 的版本号

每个接口都应定义版本号,为后续不兼容升级提供可能。当一个接口有不同的实现,项目早期使用的一个实现类, 之后创建接口的新的实现类。特别是项目需要把早期接口的实现全部换位新的实现类,也需要使用 version

可以用版本号从早期的接口实现过渡到新的接口实现,版本号不同的服务相互间不引用

可以按照以下的步骤进行版本迁移:

  • 在低压力时间段,先升级一半提供者为新版本
  • 再将所有消费者升级为新版本
  • 然后将剩下的一半提供者升级为新版本

当接口 API 变动,比如接口里面方法的参数发生变化、接口里面增加新的方法、服务增加新的接口等情况发生时,版本号的存在能让 Dubbo 的调用方替换接口的过程过度的十分平滑

除了接口的版本号之外,我们还需要关注接口的分组、注册中心已经接口的名称、全限定名等属性

Dubbo 的使用

配置的优先级如下:

  • JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口
  • XML 次之,如果在 XML 中有配置,则 dubbo.properties 中的相应配置项无效
  • Properties 最后,相当于缺省值,只有 XML 没有配置时,dubbo.properties 的相应配置项才会生效,通常用于共享公共配置,比如应用名

下面演示一下使用 xml 来配置一个可用的 dubbo,首先我们可能要将接口从服务提供方的项目中暴露出来,可以使用 xxx-api 的项目,服务方提供接口实现,而接收方使用,双方都要引入这个 xxx-api 项目

服务提供方的 xml 配置,作为服务的提供者,比服务使用方更清楚服务性能参数,如调用的超时时间,合理的重试次数。因此推荐推荐在 Provider 上尽量多配置 Consumer 端属性

<?xml version="1.0" encoding="UTF-8"?>
<!-- 添加 DUBBO SCHEMA -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- 应用名 -->
    <dubbo:application name="dubbodemo-provider"/>
    <!-- 注册中心相关配置,可以设置连接到哪个本地注册中心 -->
    <dubbo:registry id="dubbodemo" address="zookeeper://localhost:2181"/>
    <!-- 用dubbo协议在20880端口暴露服务,协议信息,提供者提供,消费者被动接受 -->
    <dubbo:protocol name="dubbo" port="28080"/>
    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service registry="dubbodemo" timeout="3000" interface="com.chanshuyi.service.IUserService" ref="userService"/>
</beans>

消费者的配置

<?xml version="1.0" encoding="UTF-8"?>
<!-- 添加 DUBBO SCHEMA -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- 应用名 -->
    <dubbo:application name="dubbodemo-consumer"/>
    <!-- 注册中心相关配置 -->
    <dubbo:registry 
    address="zookeeper://localhost:2181"
    group="tap_zk_group"
    timeout="3000"
    check="false"/>
    <!-- 消费方用什么协议获取服务(用dubbo协议在20880端口暴露服务) -->
    <dubbo:protocol name="dubbo" port="28080"/>
    <!-- 使用哪些接口 -->
    <dubbo:reference id="userService" interface="com.chanshuyi.service.IUserService"/>
</beans>

也可以通过配置的方式引用 dubbo 服务

@Configuration
public class UcenterDubboReferenceConfiguration {

    @DubboReference(id = "userInfoService", check = false, version = "2.0.0", timeout = 500, registry = "ucenter")
    private UserInfoService userInfoService;

    @Bean(name = "userInfoService")
    public UserInfoService userInfoService() {
        return userInfoService;
    }
}

简单架构

当然上面的只是关于使用的大体结构,根据官方文档 dubbo
的架构长这样
在这里插入图片描述
service 服务层:用户自定义接口API
config 配置层:对外配置接口,用以读取配置信息,以 ServiceConfig, ReferenceConfig 为中心,可以直接初始化配置类,也可以通过 spring 解析配置生成配置类
proxy 服务代理层:服务接口透明代理,简单来说是封装了下层复杂关系的代理类,让调用远程方法像调用本地的方法一样简单
registry 注册中心层:封装服务地址的注册与发现,以服务 URL 为中心,扩展接口为 RegistryFactory, Registry, RegistryService
cluster 路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以 Invoker 为中心,扩展接口为 Cluster, Directory, Router, LoadBalance
monitor 监控层:RPC 调用次数和调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactory, Monitor, MonitorService
protocol 远程调用层:封装 RPC 调用,以 Invocation, Result 为中心,扩展接口为 Protocol, Invoker, Exporter
exchange 信息交换层:封装请求响应模式,同步转异步,以 Request, Response 为中心,扩展接口为 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer
transport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec
serialize 数据序列化层:可复用的一些工具,扩展接口为 Serialization, ObjectInput, ObjectOutput, ThreadPool

SPI

你可能在上面的解释中多次看见了可扩展接口这个词,SPI 的概念类似与 API,只要实现该接口就可以对框架进行扩展

Dubbo 的扩展点加载从 JDK 标准的 SPI (Service Provider Interface) 扩展点发现机制加强而来

Dubbo 采用 微内核(Microkernel) + 插件(Plugin) 模式,简单来说就是微内核架构。微内核只负责组装插件,核心系统提供系统所需核心能力,插件模块可以扩展系统的功能

traca ID

traca ID 用于实现链路追踪,当多个 dubbo 互相调用的时候,某个地方出现错误时,排查问题就会变的十分困难。但是如果我们在每次调用的时候都生成一个唯一的 ID,我们就可以通过这个 ID,将多个日志链接起来,方便定位问题

关于 traca ID 的实现如下:

dubbo 框架提供了插件机制,其中一种插件是 Filter,利用它我们可以在调用 dubbo 接口之前和之后做一些事情。dubbo 框架还提供了 RpcContext,专门用于在远程调用的双方之间传递上下文.。上下文是静态的

下面说如何传递 trace ID:

  • 在调用方通过 filter 在调用 dubbo 接口之前,将 traceId 设置到 RpcContext 中去
  • 在被调用方,通过 filter 在实际执行之前将 traceId 从 RpcContext 中取出来设置到日志框架中的 traceId 记录器中去

SPI(service provider interface)是一种协调服务调用方与实现方的约定,约定的内容是

当服务的调用方想要发现实现接口 X 的服务实现类时,总是从 services 目录下去找文件名为 X 的文件,从这个文件中读出实现类实际的类名,从而将其加载进来并调用

机器挂掉之后 dubbo 如何维持高可用

高可用的意思是,提高一个系统中的功能可以对外提供服务的时间,减少系统不能提供服务的时间

dubbo 有自己的一些机制来保证高可用

注册中心挂掉的情况:可以使用集群来配置注册中心,提高高可用;如果所有的注册中心都挂了,消费者还有本地缓存,缓存提供服务的提供者,还可以使用dubbo直连的方式连接服务

服务器挂掉的情况:注册中心会发送信息给消费者,让其知道服务不可用;注册中心也可以直接发送代替的IP给消费者

监控中心挂掉的情况:不影响服务

协议格式

上面说过 RPC 调用需要重视传输协议的使用,那所谓协议到底是个什么东西

二进制字节流就是一串01数字,协议是为了区分每段消息长度大小以及所包含信息的。在RPC中可以使用已经有的协议,比如http、tcp,如果你喜欢用udp也可以,只要能传输数据就可以。dubbo中用了如下结构处理数据的传输

在这里插入图片描述
它与HTTP协议明显的不同就是它规定了第几个bit到第几个bit表示什么属性,回顾一下http的报文,是不是有Host:XXX、keepaliveing:XXX这种形式的信息,在XXX前的部分都可以被称为多余的字段,现在只要约定哪个区域有哪些字段就不用将这些信息传输过来了

注意RPC不是一种协议类型,只是dubbo实现了自己的协议。dubbo底层也用了tcp,它为了解决连接建立断开的损耗,默认与每个发现的provider一直保持一个长连接,同时底层使用连接池提高连接复用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值