Dubbo学习笔记

1、分布式RPC框架 Apache Dubbo学习

1.1、架构的演变:

1.1.1、单一应用架构

概念: 单体架构也称为单体系统或者是单体应用,就是一种系统中所有的功能、模块耦合在一个应用中的架构方式,一般只操作一个数据库,代表技术Struts2、SpringMVC、Spring、Mybatis等

特点: 打包成一个独立的单元(导成一个唯一的Jar包或者War包),以一个进程的方式来运行

优点: 项目易于管理,部署简单。

缺点: 测试成本高,可伸缩性差,可靠性差,迭代难度大,跨语言程度差,团队协作难。

1.1.2、RPC架构

概念: 远程过程调用。一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。代表技术:Thrift、Hessian等

特点: 应用直接调用服务,服务之间是隔离的。

缺点: 服务过多时,管理成本高昂,服务治理,服务注册,服务发现,服务容错,服务跟踪,服务网关,IP暴露等都是此架构无法避免的问题。

1.1.3、SOA架构

SOA: 面向服务架构。

ESB: 企业服务总线,服务中介,主要提供了一个服务与服务之间的交互。

ESB包含的功能: 负载均衡,流量控制,加密处理,服务的监控,异常处理,监控告急等,代表技术Mule、WS02等

1.1.4、微服务架构

微服务时一种架构风格,一个大型的复杂软件应用,由一个或多个微服务组成,系统中的各个微服务可被独立部署,各个微服务之间是松耦合的,每个微服务仅关注于完成一件任务并很好的完成该任务。微服务就是一个轻量级的服务治理方案,对比SOA架构,使用注册中心代替ESB服务总线,注册中心相比服务总线来说,更加轻量级。代表技术SpringCloud、Dubbo等

**架构风格:**项目的一种设计模式,常见的架构风格有:

1、客户端于服务端的: 在使用之前需要安装客户端的应用,如QQ、网络游戏等

2、基于组件模型的架构: 如EJB(Session Bean 实现业务逻辑的、Entity Bean 域模型、Manager Driven Bean 驱动管理模型等)

3、分层架构: 典型的就是MVC架构

4、面向服务架构: 将系统拆分成为若干个服务,业务功能基于服务管理实现,服务可独立配置、维护、运行,且多服务有统一的管理平台(ESB、注册中心)

特点: 系统是由多个服务构成,每个服务可以单独独立部署,每个服务之间是松耦合的,服务内部高内聚,外部低耦合。

优点:

测试容易: 服务高内聚低耦合,每个服务可以独立测试。

可伸缩性强: 服务相对独立,可随时增删服务,实现系统服务变化,可针对某服务独立水平拓展。

可靠性强: 服务出现问题,受影响的位置是当前服务,不会影响其它服务,应用健壮性有更好的保障。

跨语言成都会更加灵活: 可针对服务特性使用不同的语言开发,尽可能发挥出每种语言的特性。

团队协作容易: 团队专注自主研发的服务,对其它服务的了解可局限在服务的调用上。

系统迭代容易: 当服务发生变更时,只需针对单一服务进行系统升级迭代。

缺点:

运维成本高: 部署数量较多,服务过多导致运维成本成倍提升。

接口兼容多版本: 因服务可独立升级迭代,所以会导致接口版本过多。

分布式系统的复杂性: 系统分布式部署,导致通讯成本提升,系统复杂度提升。

分布式事务: 分布式系统会引出分布式事务的出现,现在有很多的分布式事务解决方案,分布式事务不是不可解决,这不会影响微服务架构的应用。

1.2、框架概述与框架结构

Dubbo是一款高性能的RPC框架,最早由阿里巴巴公司研发于2018年捐献给apache基金会。

Dubbo框架提供了三大核心能力:面向接口的远程方法调用、只能容错和负载均衡、服务自动注册和发现

Dubbo 提供的是一种 Client-Based 的服务发现机制,通常还需要部署额外的第三方注册中心组件来协调服务发现过程,如常用的 Nacos、Consul、Zookeeper 等,Dubbo 自身也提供了对多种注册中心组件的对接,可以灵活选择。

Dubbo 基于消费端的自动服务发现能力,其基本工作原理如下图:

image-20220224231752323

服务发现的一个核心组件是注册中心,Provider 注册地址到注册中心,Consumer 从注册中心读取和订阅 Provider 地址列表。 因此,要启用服务发现,需要为 Dubbo 增加注册中心配置。

  1. 服务容器负责启动,加载,运行服务提供者。

  2. 服务提供者在启动时,向注册中心注册自己提供的服务。

  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。

  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

1.3、Dubbo协议类型

Dubbo3 提供了 Triple(Dubbo3)、Dubbo2 协议,这是 Dubbo 框架的原生协议。除此之外,Dubbo3 也对众多第三方协议进行了集成,并将它们纳入 Dubbo 的编程与服务治理体系, 包括 gRPC、Thrift、JsonRPC、Hessian2、REST、HTTP、RMI 等。

协议的内容包含三部分

  • 数据交换格式: 定义 RPC 的请求和响应对象在网络传输中的字节流内容,也叫作序列化方式
  • 协议结构: 定义包含字段列表和各字段语义以及不同字段的排列方式
  • 协议通过定义规则、格式和语义来约定数据如何在网络间传输。一次成功的 RPC 需要通信的两端都能够按照协议约定进行网络字节流的读写和对象转换。如果两端对使用的协议不能达成一致,就会出现鸡同鸭讲,无法满足远程通信的需求。

RPC 协议的设计需要考虑以下内容:

  • 通用性: 统一的二进制格式,跨语言、跨平台、多传输层协议支持
  • 扩展性: 协议增加字段、升级、支持用户扩展和附加业务元数据
  • 性能:As fast as it can be
  • 穿透性:能够被各种终端设备识别和转发:网关、代理服务器等 通用性和高性能通常无法同时达到,需要协议设计者进行一定的取舍。

Triple 协议

Triple 协议是 Dubbo3 推出的主力协议。Triple 意为第三代,通过 Dubbo1.0/ Dubbo2.0 两代协议的演进,以及云原生带来的技术标准化浪潮,Dubbo3 新协议 Triple 应运而生。

dubbo 协议

dubbo 协议采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低

1.4、Dubbo连接zk集群案例

github地址:https://github.com/Aliang99/Dubbo_PCDemo

1.5、新版dubbo-admin的使用

1.5.1、下载dubbo-admin

git clone https://github.com/apache/dubbo-admin.git

1.5.2、修改zookeeper地址和超时时间

修改克隆下来的路径下的dubbo-admin\dubbo-admin-server\src\main\resources\application.properties文件,加入以下配置信息

admin.registry.address=zookeeper://192.168.1.19:2181?backup=192.168.1.33,192.168.1.34
admin.config-center=zookeeper://192.168.1.19:2181?backup=192.168.1.33,192.168.1.34
admin.metadata-report.address=zookeeper://192.168.1.19:2181?backup=192.168.1.33,192.168.1.34
dubbo.registry.timeout=20000
dubbo.metadata-report.timeout=20000

1.5.3、dubbo-admin-server模块中添加依赖

这个部分是我在使用时,总是登录出错,查找了一大堆资料才了解到需要添加这个依赖才能创建登录账号所依赖的数据库。

<dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-impl</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-core</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>javax.activation</groupId>
  <artifactId>activation</artifactId>
  <version>1.1.1</version>
</dependency>	

注意:
不加这个依赖会导致登录时出现

​ System Error, please try again later! Message:Handler dispatch failed; nested exception is java.lang.NoClassxml/bind/ DatatypeConverter以及权限验证失败问题

1.5.3、切换到dubbo-admin

cd dubbo-admin

1.5.4、打包dubbo-admin

mvn clean package

1.5.5、切换目录

cd dubbo-admin-distribution/target

1.5.6、运行

java -jar dubbo-admin-0.4.1.jar

接着在IDEA中运行服务提供者以及消费者demo

1.5.7、登录

从dubbo-admin-server的配置文件中可以看到,登录的用户名root,密码也是root

image-20220305165416054
image-20220305165143195

1.5.8、查看服务

image-20220305165254093

1.6、dubbo配置方式的使用与选择

服务提供者和服务消费者都需要配置,实现包扫描功能,扫描指定包以及子包下的类。

服务提供者在使用dubbo提供的@Service注解时,需要在配置文件中申明该注解所在的路径。

<dubbo:annotation package="com.aliang.Service">

如果未使用注解,需要在配置文件中手动指定提供服务的类

<bean id="testService" class="com.aliang.Service.impl.TestServiceImpl"/>
<dubbo:service interface="com.aliang.Service.TestService"/>

而在服务消费方,如果使用了dubbo的@Reference注解,也需要在配置文件中申明该注解所在的路径

<dubbo:annotation package="com.aliang.Controller"/>

如果未使用注解,依旧需要在配置文件中手动指定提供服务的类

<dubbo:reference id="testService" interface="com.aliang.Service.TestService"/>

以上未使用注解去发布以及引用服务的方式,只能发布或者引用一个服务,如果有多个服务,这种方式就比较繁琐了,推荐使用包扫描+注解的方式。

1.7、Dubbo负载均衡的策略以及使用

负载均衡就是将请求分摊到多个操作单元上进行执行,从而共同完成工作任务。

消费者一方,在@Reference注解上,给loadbalance属性赋值即可。

@Reference(loadbalance="random")
private TestService testService;

默认使用的负载均衡策略是随机调用,Dubbo提供的负载均衡策略有随机、轮询、最少活跃调用数、一致性Hash。

服务者一方,在@Service注解上,给loadbalance属性赋值

@Service(loadbalance="random")
public class TestServiceImpl implements TestService{
  ...
}

1.8、Dubbo的协议指定

协议具体种类以及推荐的协议参考上述1.3。

需要在服务提供者一方的@Service注解上,给protocol属性赋值,指定协议类型。

@Service(protocol="dubbo")
public class TestServiceImpl implements TestService{
  ...
}

1.9、Dubbo无法发布被事务代理的Service问题

问题出现的场景:在服务提供者类上加入了@Transactional事务控制注解后,服务发布不成功。

原因:事务控制的底层原理是为服务提供者类创建代理对象,默认情况下Spring是基于JDK动态代理方式创建对象,而此代理对象的完整类名为com.sun.proxy.$Proxy33(后两位数随机),导致Dubbo在发布服务前进行包匹配时,无法完成匹配,出现无服务发布的情况。

解决:

第一步:将Spring的代理方式修改成cglib代理

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

第二步:指定@Service注解中的接口类型

@Service(interfaceClass=TestService.class)
@Transactional
public class TestServiceImpl implements TestService{
  ...
}

使用了cglib代理后,服务提供类的接口类型默认会被代理成SpringProxy,而不是TestService。而SpringProxy也是Dubbo无法匹配的。

指定了接口类型后,cglib的代理对象实现的就是TestService接口了,Dubbo就可以根据包扫描路径而匹配到这个被事务代理的Service了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值