分布式服务调用(1)——Dubbo原理篇

一、概述

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

首先需要回答一个问题:为什么需要远程调用RPC?

为了解决高并发的问题,引入了微服务的架构,即将整体业务拆封层多个微服务,单个微服务能独立运行,那服务与服务间的调用如何保障呢?这就需要通过远程调用RPC来实现。

在将应用改造成异构、微服务的架构下,就需要再不同服务间进行数据通信,甚至在不同语言编写的服务间进行通信,所以就需要像dubbo这样的RPC框架。

dubbo不但实现RPC远程通信基本的功能外,还集成了许多服务治理的功能,比如负载均衡和流控策略、容错策略等。

二、特性

dubbo的特性既包括RPC的基础能力,也有自身的特色,包括更高效的通信机制、更丰富的服务治理能力等。

  1. 远程调用的能力:这是RPC的基本能力,在分布式架构中,服务间存在远程调用;在异构应用中,不同编程语言的服务存在调用,目前dubbo 3.x能够支持Java和Golang等语言;
  2. 高效和丰富的远程通信机制:dubbo支持丰富的通信协议,一般都是基于TCP协议进行开发的,相对与HTTP协议,他有更好的性能,并且能够做更多自定义的开发,包括自定义通信协议格式或流控重试策略等;
  3. 服务注册和服务发现:可以通过服务注册中心来集中式管理服务,服务提供者将服务注册到注册中心,服务消费者从注册中心获取服务列表,同时能通过监控中心来监控服务使用情况;
  4. 负载均衡和容错处理:dubbo在调用服务存在多实例的时候,有丰富的负载均衡策略;在存在调用失败的时候,也有完善的流控策略和容错策略。

三、原理

1.RPC原理

首先需要搞清楚常见RPC框架必须的组件,常见RPC需要实现的组件有:

  1. 序列化和反序列化:进行远程通信的数据需要进行序列化后才进行传输,他们的序列号方式一般有二进制编码和文本编码格式,二进制的编码包括protobuf格式,文本编码格式中最常见的是json格式;
  2. 网络通信:服务消费者和服务提供者进行数据通信的协议,一般有Netty和或者JDK原生的NIO等协议;
  3. 动态代理:一般通过动态代理的方式实现,比如最简单通过JDK原生的动态代理实现;

2.架构设计

dubbo的官方架构图:

节点 角色说明
Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次数和调用时间的监控中心
Container 服务运行容器

dubbo的整体架构也是生产者/消费者模式,只是在此基础上新增了注册中心和监控中心的角色。整个流程如下:

  1. 服务提供者启动服务,会将服务信息注册到注册中心去;
  2. 服务消费者启动服务,会订阅注册中心的服务列表,服务有更新,则同步更新本地的服务列表;
  3. 当服务消费者需要调用远程的服务提供者时,就会从服务列表中获取远程的服务信息,通过远程通信的方式调用对端服务,对端的服务实例通过动态代理的方式生成服务实例,再返回响应;
  4. 这样的一次远程服务调用会记录在监控中心中;

分布式系统中随着服务的增多,服务间的访问愈发负载,所以需要一个中心化的注册中心来管理服务,Dubbo就有这样的特性,拥有一个中心化的服务注册中心,服务提供方将服务注册到注册中心,服务消费方从注册中心获取服务信息,再进行远程调用;每次进行远程调用都会记录在监控中心中。

3.重要组件

Dubbo中服务端最核心的对象有四个:

  1. ApplicationConfig:配置当前应用信息
  2. ProtocolConfig:配置提供服务的协议信息
  3. RegistryConfig:配置注册相关信息
  4. ServiceConfig:配置暴露的服务信息

Dubbo客户端中核心的对象有两个:

  1. ApplicationConfig:配置当前应用信息
  2. ReferenceConfig:配置引用的服务信息

4.负载均衡

dubbo实现的是客户端负载均衡,消费者拉取了服务提供方列表,通过负载均衡算法进行负载。

负载均衡模式 说明 使用方法
Random LoadBalance 随机 按权重设置随机概率 <dubbo:service loadbalance="xxx"/> xxx:负载均衡方法
RoundRobin LoadBalance 轮询 按公约后的权重设置轮询比率。
LeastActive LoadBalance 最少活跃调用数 相同活跃数的随机,活跃数指调用前后计数差。
ConsistentHash LoadBalance 一致性 Hash 相同参数的请求总是发到同一提供者。 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

5.容错机制

dubbo 也是支持集群容错的,同时也有很多可选的方案,其中,默认的方案是 failover,也就是重试机制。

集群模式 说明 使用方法
Failover Cluster 失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。 cluster="xxx" xxx:集群模式名称 ,例如cluster="failover"
Failfast Cluster 快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
Failsafe Cluster 失败安全,出现异常时,直接忽略。
Failback Cluster 失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
Forking Cluster 并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。
Broadcast Cluster 广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。

四、总结

1.dubbo和spring cloud的比较

核心区别是在网络通信协议选择方面,Spring Cloud的服务调用是选择基于HTTP的网络通信模式,而Dubbo选择的是自定义的基于TCP模式的网络通信模式,相对来说,后者定制化程度更高,性能更好。

2.dubbo和gRPC的比较

dubbo和gRPC都是非常优秀的RPC框架,他们的区别在于:

  1. gRPC支持更多语言的服务调用,目前dubbo在后端领域主要还是支持Java生态;
  2. Dubbo具有更丰富的服务治理能力,包括负载均衡和流控等策略,都是gRPC欠缺的;
  3. 针对序列化的方案,目前gRPC只支持protobuf,dubbo支持更丰富的序列号方案;

参考文献

Dubbo两小时快速上手教程(直接代码、Spring、SpringBoot):https://juejin.cn/post/6949558189733969951#heading-6 (介绍了3中dubbo的使用方式)

Dubbo 一篇文章就够了:从入门到实战:https://segmentfault.com/a/1190000019896723 (重点关注负载均衡和容错机制)

RPC框架的组成:https://blog.csdn.net/hdughy/article/details/119995403 (解释了RPC的通用架构)

本文由博客一文多发平台 OpenWrite 发布!

相关推荐
jerry6094 小时前
7天用Go从零实现分布式缓存GeeCache(改进)(未完待续)
分布式·缓存·golang
古人诚不我欺5 小时前
jmeter常用配置元件介绍总结之分布式压测
分布式·jmeter
星染xr8 小时前
kafka 生产经验——数据积压(消费者如何提高吞吐量)
分布式·kafka
东方巴黎~Sunsiny8 小时前
如何监控Kafka消费者的性能指标?
分布式·kafka
飞升不如收破烂~8 小时前
kafka
分布式·kafka
龙哥·三年风水9 小时前
群控系统服务端开发模式-应用开发-前端个人信息功能
分布式·vue·群控系统
小码哥呀10 小时前
RabbitMQ集群搭建
分布式·rabbitmq
材料苦逼不会梦到计算机白富美11 小时前
golang分布式缓存项目 Day6 防止缓存击穿
分布式·缓存·golang
Yz987613 小时前
Kafka面试题
大数据·分布式·zookeeper·kafka·big data
林子漾14 小时前
【paper】分布式无人水下航行器围捕智能目标
分布式·wpf