分布式架构-Dubbo框架(一):从0到1整体认知分布式系统

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z785495295/article/details/84402968

概要:

  1. 分布式架构的发展历史与背景
  2. 如何着手架构一套分布示式系统
  3. Dubbo 架构与设计说明 


一、分布式架构的发展历史与背景


场景一:
一家做政务OA系统的公司老板发现跟竞争对手比发现自己的系统的架构不是分布示
的,找到技术负责人问,把系统架构升级成分布示架构要多长时间?技术负责人网上查了查
dubbo官网看了看 Demo 这不很简单吗,拍着胸脯一个月能升级好。
现在我的问题是:这位技术理在改造过程中可能会遇到什么风险和问题?
1. 新功能和旧BUG的问题
2. 业务完整性的问题
3. 团队协作方式转变
4. 开发人员技能提升
5. 系统交付方式转变
这些问题解决涉及业务部门及整个技术部门(开发、测试、运维)协商与工作标准的制定。业
务相关问题暂不做讨论,技术架构上应该要清楚自己的职责是,如何通过技术手段把业务波动
降至最低、开发成本最低、实施风险最低?
要解决这些问题的前提之一就是要对分布式架构有整体的认知,今天课程就通过三个知识点讲
解来提高大家对分布示架构的整体认知:
1. 系统架构的发展历史
2. 一套分布式系统的组成
3. 分布式架构所带来的成本与风险

架构的发展历史:


单体式架构:

垂直架构:

分布示架构:

分布式架构所带来的成本与风险

分布式事物:
分布式事物是指一个操作,分成几个小操作在多个服务器上执行,要么多成功,要么多失败
这些分布事物要做的
不允许服务有状态(stateless service)
无状态服务是指对单次请求的处理,不依赖其他请求,也就是说,处理一次请求所需的全部信
息,要么都包含在这个请求里,要么可以从外部获取到(比如说数据库),服务器本身不存储
任何信息。
服务依懒关系复杂
服务 A --> B--> C 那和服务C 的修改 就可能会影响 B 和C,事实上当服务越来 越多的时
候,C的变动将会越来越困难。
部署运维成本增加
不用说了,相比之前几个节点,运维成本的增加必须的。
源码管理成本增加:
原本一套或几套源码现在拆分成几十个源码库,其中分支、tag都要进行相应管理。
如何保证系统的伸缩性:
伸缩性是指,当前服务器硬件升级后或新增服务器处理能力就能相对应的提升。
分布式会话:
此仅针对应用层服务,不能将Session 存储在一个服务器上。
分布式JOB
通常定时任务只需要在一台机器上触发执行,分布式的情况下在哪台执行呢?

最后通过一张图直观感受一下 单体到分布式的区别:

二、如何选型分布式架构


提问:实现一个分布示框架最核心功能是什么?
RPC远程调用技术:

大家知道的 有哪些远程调用的 方式?拿几个大家比较熟悉的来举例:RMI 、WebService、Http

协议

描述

优点

缺点

RMI

JAVA 远程方法调用、使用原生二进制方式进行序列化

简单易用、SDK支持,提高开发效率

不支持跨语言

Web Service

比较早系统调用解决方案 ,跨语言, 其基于WSDL 生成 SOAP 进行消息的传递。

SDK支持、跨语言

实现较重,发布繁琐

Http

采用htpp +json 实现

简单、轻量、跨语言

不支持SDK

基于比较上述比较,大家会选择哪个方案,综合考虑 RMI是比较合适的方案,基本没有学习
成本。而跨语言问题基本可以勿略。
如果服务端不是单个的话,这个方案差点我就用了。实际上服务端是多个的 ,好了新的
问题又来了。

1、负载均衡:这么多个机器调用哪一台?
2、容错:如果调用其中一台调用出错了怎么办?
3、服务配置:服务端地址配置在哪里?
4、健康检测:服务关宕机或恢复后怎么办?

这些功能怎么解决呢?一个一个的去编码实现么?。有没有现成的方案可以直接借鉴呢?

分布式架构的三种类别:
1. 中心化架构
2. 去中心化架构
3. 服务网格servicemesh
这些功能怎么解决呢?一个一个的去编码实现么?。有没有现成的方案可以直接实现这些功
能?

分布式架构的三种解决方案:

  1. 基于反向代理的中心化架构
  2. 嵌入应用内部的去中心化架构
  3. 基于独立代理进程的Service Mesh架构

基于反向代理的集中式分布式架构

这是最简单和传统做法,在服务消费者和生产者之间,代理作为独立一层集中部署,由独立团队(一般是运维或框架)负责治理和运维。常用的集中式代理有硬件负载均衡器(如F5),或者软件负载均衡器(如Nginx),这种软硬结合两层代理也是业内常见做法,兼顾配置的灵活性(Nginx比F5易于配置)。

Nginx完全支持这些功能。所以企业在做轻量级架构 会采用 Http+Nginx 方式。

 

 

可能就要问了,Nginx那不就单点了吗?Nginx本身还可以根据业务进行垂直拆分,变更
之后如下图。

Http+Nginx  方案总结:

 

优点:简单快速、几乎没有学习成本

适用场景:轻量级分布式系统、局部分布式架构。

瓶颈:Nginx中心负载、Http传输、JSON序列化、开发效率、运维效率。

嵌入应用内部的去中心化架构

这是很多互联网公司比较流行的一种做法,代理(包括服务发现和负载均衡逻辑)以客户库的形式嵌入在应用程序中。这种模式一般需要独立的服务注册中心组件配合,服务启动时自动注册到注册中心并定期报心跳,客户端代理则发现服务并做负载均衡。我们所熟悉的 duboo 和spring cloud Eureka +Ribbon/'rɪbən/ 都是这种方式实现。

相比第一代架构它有以下特点几点:

  1. 去中心化,客户端直连服务端
  2. 动态注册和发现服务
  3. 高效稳定的网络传输
  4. 高效可容错的序列化

基于独立代理进程的架构(Service Mesh)

这种做法是上面两种模式的一个折中,代理既不是独立集中部署,也不嵌入在客户应用程序中,而是作为独立进程部署在每一个主机上,一个主机上的多个消费者应用可以共用这个代理,实现服务发现和负载均衡,如下图所示。这个模式一般也需要独立的服务注册中心组件配合,作用同第二代架构。

基于瓶颈考虑大型系统需要一个更加专业的方案,该方案必须做到以下几点:
1. 去中心化,客户端直连服务端
2. 动态注册和发现服务
3. 软负载均衡实现
4. 高效稳定的网络传输
5. 高效可容错的序列化

其对应的功能组件如下:

1. 注册中心逻辑:
2. 服务端动态注册服务提供者信息
3. 客户端从注册中心接收服务提供者信息,并存储至本地缓存
4. 注册中心实时监听提供者状态,如果变更将即时通知客户端
5. 调用逻辑:
6. 负载均衡
7. 容错
8. 对服务调用者透明
9. 传输模块:
10. minal,servlet 容器、netty
11. 序列化模块:
12. kryo、hessian、java、protobuf、JSON、XML

三种架构的比较

模式

优点

缺点

适应场景

案例

集中式负载架构

简单

集中式治理

与语言无关

配置维护成本高

多了一层IO

单点问题

大部分公司都适用,对运维有要求

亿贝、携程、早期互联网公司

客户端嵌入式架构

无单点

性能更好

客户端复杂

语言栈要求

中大规模公司、语言栈统一

Dubbo 、

Twitter finagle、

Spring Cloud Ribbon

独立进程代理架构

无单点

性能更好

与语言无关

运维部署复杂

开发联调复杂

中大规模公司

对运维有要求

Smart Stack

Service Mesh

三、Dubbo 架构与设计说明

dubbo架构简要讲解
架构图

流程说明:
1. Provider(提供者)绑定指定端口并启动服务
2. 指供者连接注册中心,并发本机IP、端口、应用信息和提供服务信息发送至注册中心存储
3. Consumer(消费者),连接注册中心 ,并发送应用信息、所求服务信息至注册中心
4. 注册中心根据 消费 者所求服务信息匹配对应的提供者列表发送至Consumer 应用缓存。
5. Consumer 在发起远程调用时基于缓存的消费者列表择其一发起调用。
6. Provider 状态变更会实时通知注册中心、在由注册中心实时推送至Consumer
这么设计的意义:
1. Consumer 与Provider 解偶,双方都可以横向增减节点数。
2. 注册中心对本身可做对等集群,可动态增减节点,并且任意一台宕掉后,将自动切换到另
一台
3. 去中心化,双方不直接依懒注册中心,即使注册中心全部宕机短时间内也不会影响服务的
调用
4. 服务提供者无状态,任意一台宕掉后,不影响使用

Dubbo 整体设计

  1. config 配置层:对外配置接口,以 ServiceConfig, ReferenceConfig 为中心,可以直接初始化配置类,也可以通过 spring 解析配置生成配置类
  2. proxy 服务代理层:服务接口透明代理,生成动态代理 扩展接口为 ProxyFactory
  3. registry 注册中心层:封装服务地址的注册与发现,以服务 URL 为中心,扩展接口为 RegistryFactory, Registry, RegistryService
  4. cluster 路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以 Invoker 为中心,扩展接口为 Cluster, Directory, Router, LoadBalance
  5. monitor 监控层:RPC 调用次数和调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactory, Monitor, MonitorService
  6. protocol 远程调用层:封装 RPC 调用,以 Invocation, Result 为中心,扩展接口为 Protocol, Invoker, Exporter
  7. exchange 信息交换层:封装请求响应模式,同步转异步,以 Request, Response 为中心,扩展接口为 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer
  8. transport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec
  9. serialize 数据序列化层:可复用的一些工具,扩展接口为 Serialization, ObjectInput, ObjectOutput, ThreadPool

其协作流程如下: 

 

Dubbo 中的SPI机制
在了解Dubbo的spi之前 先来了解一下 JAVA自带的SPI
java spi的具体约定为:当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-
INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的
具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里
的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能
很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类
java.util.ServiceLoader
演示JAVA SPI机制

  1. 编写接口
  1. 编写实现类
  1. 编辑META-INF/services/xxx 文件
  1. 演示spi 实现


spi 目录文件:

META-INF/services/tuling.dubbo.server.UserService 中的值:

tuling.dubbo.server.impl.UserServiceImpl2


装载获取SPI实现类:

public static void main(String[] args) {
    Iterator<UserService> services = ServiceLoader.load(UserService.class).iterator();
    UserService service = null;
    while (services.hasNext()) {
        service = services.next();
    }
    System.out.println(service.getUser(111));
}


Dubbo的SPI机制:
dubbo spi 在JAVA自带的SPI基础上加入了扩展点的功能,即每个实现类都会对应至一个扩
展点名称,其目的是 应用可基于此名称进行相应的装配。
演示Dubbo SPI机制:

  1. 编写Filter 过滤器
  1. 编写 dubbo spi 配置文件
  1. 装配自定义Filter


dubbo spi 目录文件

dubbo spi 文件内容:

luban=tuling.dubbo.server.LubanFilter


装配自定义Filter

猜你喜欢

转载自blog.csdn.net/z785495295/article/details/84402968