Dubbo 学习笔记总结

Dubbo


1.什么是RPC?

RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据

RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。现在业界有很多开源的优秀 RPC 框架,例如 Spring Cloud、Dubbo、Thrift 等。


2.RPC工作原理在这里插入图片描述

  1. Client(客户端)像调用本地服务似的调用远程服务;
  2. Client stub(客户端存根)接收到调用后,将方法、参数序列化
  3. 客户端通过sockets将消息发送到服务端
  4. Server stub(服务端存根) 收到消息后进行解码(将消息对象反序列化)
  5. Server stub (服务端存根)根据解码结果调用本地的服务
  6. 本地服务执行(对于服务端来说是本地执行)并将结果返回给Server stub
  7. Server stub将返回结果打包成消息(将结果消息对象序列化)
  8. 服务端通过sockets将消息发送到客户端
  9. Client stub接收到结果消息,并进行解码(将结果消息发序列化)
  10. 客户端得到最终结果。

3.RPC步骤解析

在这里插入图片描述


4.dubbo设计架构

在这里插入图片描述
  该图来自Dubbo官网,描述了服务注册中心、服务提供方、服务消费方、服务监控中心之间的调用关系。

   Dubbo官网: https://dubbo.apache.org/zh/docs/

  • 服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。
  • 服务消费者(Consumer): 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  • 注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  • 监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用

5.springboot 搭建 dubbo项目

5.1 创建服务提供者项目

  1. 创建Maven项目 boot-user-service-provider 服务提供者
      导入dubbo依赖
		<dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>0.2.0</version>
        </dependency>
  1. user-service-provider项目中的 service层中使用 @Service 注解(使用dubbo的)
@Service//dubbo的服务暴露
@Component
public class UserServiceImpl implements UserService {
	public List<UserAddress> getUserAddressList(String userId) {

		UserAddress address1 = new UserAddress(1, "河南省郑州巩义市宋陵大厦2F", "1", "安然", "150360313x", "Y");
		UserAddress address2 = new UserAddress(2, "北京市昌平区沙河镇沙阳路", "1", "情话", "1766666395x", "N");

		return Arrays.asList(address1,address2);
	}
}
  1. 配置 application.properties
dubbo.application.name=boot-user-service-provider
dubbo.registry.address=127.0.0.1:2181
dubbo.registry.protocol=zookeeper

dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

#连接监控中心
dubbo.monitor.protocol=registry
  1. 在启动配置类上 添加 @EnableDubbo注解
@EnableDubbo //开启基于注解的dubbo功能
@SpringBootApplication
public class BootProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(BootProviderApplication.class, args);
    }
}

5.2 创建服务消费者项目

  1. 创建Maven项目 boot-order-service-consumer 服务消费者
      导入dubbo依赖
		<dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>0.2.0</version>
        </dependency>
  1. boot-order-service-consumer 项目中的 service层中使用 @Reference 注解(使用dubbo的)
@Service
public class OrderServiceImpl implements OrderService {

    @Reference//引用远程提供者服务
    UserService userService;

    public List<UserAddress> initOrder(String userID) {
        //查询用户的收货地址
        List<UserAddress> userAddressList = userService.getUserAddressList(userID);

        System.out.println("当前接收到的userId=> "+userID);
        System.out.println("**********");
        System.out.println("查询到的所有地址为:");
        for (UserAddress userAddress : userAddressList) {
            //打印远程服务地址的信息
            System.out.println(userAddress.getUserAddress());
        }
        return userAddressList;
    }
}
  1. 创建 OrderController 控制器
@Controller
public class OrderController {
    @Autowired
    OrderService orderService;

    @RequestMapping("/initOrder")
    @ResponseBody
    public List<UserAddress> initOrder(@RequestParam("uid")String userId) {
        return orderService.initOrder(userId);
    }
}

  1. 配置 application.properties
server.port=8081
dubbo.application.name=boot-order-service-consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181

#连接监控中心 注册中心协议
dubbo.monitor.protocol=registry
  1. 在启动配置类上 添加 @EnableDubbo注解
@EnableDubbo //开启基于注解的dubbo功能
@SpringBootApplication
public class BootConsumerApplication {
    public static void main(String[] args){
        SpringApplication.run(BootConsumerApplication.class,args);
    }
}

  配置完毕,此时启动zookeeper注册中心及监控。
  启动springboot配置的服务提供者和消费者
  在浏览器输入 localhost:7001 查看结果
在这里插入图片描述
查询到地址信息在这里插入图片描述
至此:duboo的springboot整合配置完成。


6.Dubbo配置

dubbo配置官网参考:https://dubbo.apache.org/zh/docs/v2.7/user/examples/preflight-check/

6.1、配置原则

在这里插入图片描述

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

6.2、启动时检查

  在启动时检查依赖的服务是否可用

  Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check=“true”。

  可以通过 check=“false” 关闭检查,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。

  另外,如果你的 Spring 容器是懒加载的,或者通过 API 编程延迟引用服务,请关闭 check,否则服务临时不可用时,会抛出异常,拿到 null 引用,如果 check=“false”,总是会返回引用,当服务恢复时,能自动连上。

dubbo.reference.com.foo.BarService.check=false
// 强制改变所有 reference 的 check 值,就算配置中有声明,也会被覆盖
dubbo.reference.check=false
// 是设置 check 的缺省值,如果配置中有显式的声明,如:<dubbo:reference check="true"/>,不会受影响。
dubbo.consumer.check=false
// 前面两个都是指订阅成功,但提供者列表是否为空是否报错,如果注册订阅失败时,也允许启动,需使用此选项,将在后台定时重试。
dubbo.registry.check=false

6.3、配置的覆盖关系

  不同粒度配置的覆盖关系

  以 timeout 为例,下图显示了配置的查找顺序,其它 retries, loadbalance, actives 等类似:

  •  方法级优先,接口级次之,全局配置再次之。
  •  如果级别一样,则消费方优先,提供方次之。

其中,服务提供方配置,通过 URL 经由注册中心传递给消费方。
在这里插入图片描述

6.4、重试次数

retries :远程服务调用重试次数,不包括第一次调用,不需要重试请设为0。

<dubbo:reference interface="com.xxx.XxxService">
    <dubbo:method name="findXxx" timeout="3000" retries="2" />
</dubbo:reference>

6.5、幂等性与非幂等性

  •  幂等:无论程序执行多少次,其结果都是相同的。【比如:查询、修改、删除】

  •  非幂等:程序每执行一个结果都不一样。【比如:新增】

6.6、多版本

在 Dubbo 中为同一个服务配置多个版本

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。

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

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

老版本服务提供者配置:

<dubbo:service interface="com.foo.BarService" version="1.0.0" />

新版本服务提供者配置:

<dubbo:service interface="com.foo.BarService" version="2.0.0" />

老版本服务消费者配置:

<dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" />

新版本服务消费者配置:

<dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />

如果不需要区分版本,可以使用 *

提示:2.2.0 以上版本支持

<dubbo:reference id="barService" interface="com.foo.BarService" version="*" />

6.7、dubbo与springboot整合的三种方式

Springboot与Dubbo整合的三种方式

  •  1、 导入dubbo-starter。在application.properties配置属性,使用@Service【暴露服务】,使用@Reference【引用服务】

  •  2、保留Dubbo 相关的xml配置文件

    • 导入dubbo-starter,使用@ImportResource导入Dubbo的xml配置文件
  •  3、使用 注解API的方式

将每一个组件手动配置到容器中,让dubbo来扫描其他的组件


7、高可用

7.1、zookeeper宕机与dubbo直连

现象:zookeeper注册中心宕机,还可以消费dubbo暴露的服务。

原因:

  •  监控中心宕掉不影响使用,只是丢失部分采样数据
  •  数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
  •  注册中心对等集群,任意一台宕掉后,将自动切换到另一台
  • 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
  •  服务提供者无状态,任意一台宕掉后,不影响使用
  •  服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

高可用:通过设计,减少系统不能提供服务的时间;

代码实现:在service层中的 @Reference注解后添加参数

@Reference(url = "127.0.0.1:20882")
UserService userService;

7.1、负载均衡机制

  在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省(默认)为 random 随机调用

1、 Random LoadBalance

  • 随机,按权重设置随机概率。
  •  在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
    在这里插入图片描述

2、 RoundRobin LoadBalance

  • 轮询,按公约后的权重设置轮询比率
  •  存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
    在这里插入图片描述

3、 LeastActive LoadBalance

  • 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
  •  使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
    在这里插入图片描述

4、 ConsistentHash LoadBalance

  • 一致性 Hash,相同参数的请求总是发到同一提供者。
  •  当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
  •  算法参见:http://en.wikipedia.org/wiki/Consistent_hashing
  •  缺省只对第一个参数 Hash,如果要修改,请配置 <dubbo:parameter key=“hash.arguments” value=“0,1” />
  •  缺省用 160 份虚拟节点,如果要修改,请配置 <dubbo:parameter key=“hash.nodes” value=“320” />
    在这里插入图片描述

代码实现:在service层中的 @Reference注解后添加参数

@Reference(loadbalance="roundrobin")
UserService userService;

7.3、整合hystrix,服务熔断与降级处理


7.3.1、服务降级

服务降级
  当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。

  可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。

  向注册中心写入动态配置覆盖规则:

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();

Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));

registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null"));

其中:

  •  mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
  •  还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

7.3.2、集群容错

在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failover 重试。

集群容错模式

  • Failover Cluster
     失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。
重试次数配置如下:
<dubbo:service retries="2" /><dubbo:reference retries="2" /><dubbo:reference>
    <dubbo:method name="findFoo" retries="2" />
</dubbo:reference>

  • Failfast Cluster
     快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。

  • Failback Cluster
     失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。

  • Failsafe Cluste
     失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。

  • Forking Cluster
     并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=“2” 来设置最大并行数。

  • Broadcast Cluster
     广播调用所有提供者,逐个调用,任意一台报错则报错 [2]。通常用于通知所有提供者更新缓存或日志等本地资源信息。

  • 集群模式配置
     按照以下示例在服务提供方和消费方配置集群模式

<dubbo:service cluster=“failsafe” /><dubbo:reference cluster=“failsafe” />

7.3.3、整合hystrix

   Hystrix 旨在通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能

配置spring-cloud-starter-netflix-hystrix

spring boot官方提供了对hystrix的集成,直接在pom.xml里加入依赖:

 <dependency>
     <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
      <version>1.4.4.RELEASE</version>
</dependency>

然后在Application类上增加@EnableHystrix来启用hystrix starter:

@SpringBootApplication
@EnableHystrix //开启服务容错功能
public class ProviderApplication {
	...启动方法
}

配置Provider端

   在Dubbo的Provider上增加@HystrixCommand配置,这样子调用就会经过Hystrix代理。

@Service(version = "1.0.0")
public class HelloServiceImpl implements HelloService {
    @HystrixCommand(commandProperties = {
     @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
     @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000") })
    @Override
    public String sayHello(String name) {
        // System.out.println("async provider received: " + name);
        // return "annotation: hello, " + name;
        throw new RuntimeException("Exception to show hystrix enabled.");
    }
}

配置Consumer端

   对于Consumer端,则可以增加一层method调用,并在method上配置@HystrixCommand。当调用出错时,会走到fallbackMethod = "reliable"的调用里。

@Reference(version = "1.0.0")
    private HelloService demoService;

    @HystrixCommand(fallbackMethod = "reliable")
    public String doSayHello(String name) {
        return demoService.sayHello(name);
    }
    public String reliable(String name) {
        return "hystrix fallback value";
    }


8、dubbo原理


8.1、RPC原理

在这里插入图片描述
一次完整的RPC调用流程(同步调用,异步另说)如下:

  1. 服务消费方(client)调用以本地调用方式调用服务;
  2. client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
  3. client stub找到服务地址,并将消息发送到服务端;
  4. server stub收到消息后进行解码;
  5. server stub根据解码结果调用本地的服务;
  6. 本地服务执行并将结果返回给server stub;
  7. server stub将返回结果打包成消息并发送至消费方;
  8. client stub接收到消息,并进行解码;
  9. 服务消费方得到最终结果。

   dubbo只用了两步1和8,中间的过程是透明的看不到的。RPC框架的目标就是要2~8这些步骤都封装起来,这些细节对用户来说是透明的,不可见的。


9、dubbo原理


9.1、dubbo原理 -框架设计

在这里插入图片描述
依次从最外层开始分析:

  • business:业务逻辑层(我们只写这一层,其他的都是dubbo底层)
    • Service :服务层。面向接口编程,写一个接口和一个实现类
  •   RPC:远程过程调用
    • Config: 配置层(主要是封装我们配置文件里面解析出来的一些信息,以 ServiceConfig, ServiceConfig为中心,也就是说每一个标签都有一个对应的配置类,来配置这些信息)
    • proxy 服务代理层: 服务接口透明代理,生成服务的客户端 Stub(代理对象)服务器端 Skeleton(代理对象), 以 ServiceProxy 为中心,扩展接口为 ProxyFactory
    • registry 注册中心层: 封装服务地址的注册与发现,以服务 URL 为中心,扩展接口为 RegistryFactory, Registry, RegistryService
    • cluster 路由层: 封装多个提供者的路由负载均衡,并桥接注册中心,以 Invoker 为中心,扩展接口为 Cluster, Directory, Router, LoadBalance
    • monitor 监控层: RPC 调用次数和调用时间监控(调用展示监控数据),以 Statistics 为中心,扩展接口为MonitorFactory , Monitor, MonitorService
    • protocol 远程调用层: 封装整个 RPC 调用,以 Invocation, Result 为中心,扩展接口为 Protocol, Invoker, Exporter
  • Remoting 远程通讯层
    • exchange 信息交换层: 主要就是架起一个客户端和服务端,让他们互联互通。 封装请求响应模式,同步转异步,以 Request, Response 为中心,扩展接口为 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer
    • transport 网络传输层: 抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec
    • serialize 数据序列化层: 数据的序列化传输与反序列化解析。 可复用的一些工具,扩展接口为 Serialization, ObjectInput, ObjectOutput, ThreadPool

9.2、dubbo原理 -启动解析、加载配置信息

在这里插入图片描述

9.3、dubbo原理 -服务暴露在这里插入图片描述


9.4、dubbo原理 -服务引用

在这里插入图片描述


9.5、dubbo原理 -服务调用

在这里插入图片描述


10、参考

文章参考视频:B站 雷神将 Dubbo 教程

文章参考博客:CSDN Dubbo入门介绍及学习笔记总结












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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值