dubbo分布式服务框架(高级特性篇)

简介: 本文详细介绍并实际操作dubbo常用高级特性,序列化、地址缓存、超时、重试、负载均衡、多版本、集群容错、服务降级

 1.序列化

序列化是将Java对象转化为流的数据,流的数据才能在两台主机上进行传输

image.gif

dubbo内部已经对序列化和反序列化封装了,我们只需要让实体类实现Serializable接口即可

文章基于本人另一篇博客dubbo入门篇

dubbo分布式服务框架入门_雪月清的博客-CSDN博客

1.新建一个模块为dubbo-pojo,创建一个User类(先不实现Serializable接口)

public class User {
     private int id;
     private  String name;
     private  String password;
     public User() {
     }
     public User(int id, String name, String password) {
         this.id = id;
         this.name = name;
         this.password = password;
     }
     public int getId() {
         return id;
     }
     public void setId(int id) {
         this.id = id;
     }
     public String getName() {
         return name;
     }
     public void setName(String name) {
         this.name = name;
     }
     public String getPassword() {
         return password;
     }
     public void setPassword(String password) {
         this.password = password;
     }
 }

image.gif

2.在dubbo-interface中关联dubbo-pojo,因为我们在接口模块写一个测试user的接口

<dependencies>
     <dependency>
         <groupId>com.xue</groupId>
         <artifactId>dubbo-pojo</artifactId>
         <version>1.0-SNAPSHOT</version>
     </dependency>
 </dependencies>

image.gif

在UserService接口中新增一个方法

/**
  * 查询用户接口
  * @return
  */
 public User findUserById(int id);

image.gif

3.在dubbo-service模块中实现此方法,并简单返回一个测试的user对象

@Override
     public User findUserById(int id) {
         User[]users = {new User(1,"雪月清","123")
                 ,new User(2,"张三","456")
                 ,new User(3,"李四","156")};
         return users[id-1];
     }

image.gif

4.在dubbo-web模块下的UserController中新增find方法

@RequestMapping("/find")
 public User find(int id) {
     return userService.findUserById(id);
 }

image.gif

然后进行tomcat7:run进行测试

然后测试就发现报错了

image.gif

控制台报错信息

java.lang.IllegalStateException: Serialized class com.xue.pojo.User must implement java.io.Serializable

image.gif

需要实现Serializable接口

public class User implements Serializable

image.gif

重新启动

image.gif

成功访问!

2.地址缓存

面试题:注册中心挂了,服务是否可以正常访问?

可以,因为dubbo服务消费者在第一次调用时,会将服务提供方地址缓存到本地,以后在调用就不会访问注册中心。

当服务提供者地址发生变化时,注册中心会通知服务消费者

停掉zookeeper服务注册中心

image.gif

访问成功!

image.gif

3.超时

问题描述:

服务消费者在调用服务提供者的时候发生了阻塞、等待的情形,这个时候,服务消费者会一

直等待下去。在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大量堆

积,势必会造成雪崩

dubbo利用超时机制来解决这个问题,设置一个超时时间,在这个时间段内,无法完成服务

访问,则自动断开连接。

使用timeout属性配置超时时间,默认值1000,单位毫秒。

1.在dubbo-service模块中配置超时时间,并模拟超时

@Service(timeout = 3000)
 public class UserServiceImpl implements UserService {
     @Override
     public String demo() {
         return "hello,Dubbo";
     }
     @Override
     public User findUserById(int id) {
         User[]users = {new User(1,"雪月清","123")
                 ,new User(2,"张三","456")
                 ,new User(3,"李四","156")};
         //模拟超时
         try {
             Thread.sleep(5000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         return users[id-1];
     }
 }

image.gif

2.访问失败,超时

image.gif

注意点

在服务消费方@Reference也可以配置超时时间,并且会覆盖服务提供方的超时时间,也就是说@Reference配置1s,之前服务提供方配置3s,最后结果是1s之后就发生超时

@Reference(timeout = 1000) //远程注入
 private UserService userService;

image.gif

建议在服务提供方配置超时时间,毕竟这个服务是服务提供方编写的,在编写时就应该考虑超时时间的配置问题

4.重试

设置了超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。如果出现网络抖动(网

络突然断掉又重新连接上,网络不稳定),则这一次请求就会失败。

Dubbo提供重试机制来避免类似问题的发生。通过retries属性来设置重试次数,默认为2次。(总

共发了三次)

@Service(timeout = 3000,retries = 2) //当前服务3秒超时,重视2次,一共3次
 public class UserServiceImpl implements UserService {
     int i = 1;
     @Override
     public String demo() {
         return "hello,Dubbo";
     }
     @Override
     public User findUserById(int id) {
         System.out.println("服务被调用"+i++);
         User[]users = {new User(1,"雪月清","123")
                 ,new User(2,"张三","456")
                 ,new User(3,"李四","156")};
         //模拟超时
         try {
             Thread.sleep(5000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         return users[id-1];
     }
 }

image.gif

进行了超时重试

image.gif

5.多版本

灰度发布: 当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁

移到新功能。

image.gif

V2.0版本没问题之后再将所有用户迁移到V2.0

image.gif

dubbo中使用version属性来设置和调用同一个接口的不同版本

@Service(version = "v1.0")
 public class UserServiceImpl implements UserService {
     @Override
     public String demo() {
         return "hello,Dubbo";
     }
     @Override
     public User findUserById(int id) {
         System.out.println("v1.0版本");
         User[]users = {new User(1,"雪月清","123")
                 ,new User(2,"张三","456")
                 ,new User(3,"李四","156")};
         return users[id-1];
     }
 }

image.gif

1.复制UserServiceImpl类并改为v2.0版本

@Service(version = "v2.0") 
 public class UserServiceImpl2 implements UserService {
     @Override
     public String demo() {
         return "hello,Dubbo";
     }
     @Override
     public User findUserById(int id) {
         System.out.println("v2.0版本");
         User[]users = {new User(1,"雪月清","123")
                 ,new User(2,"张三","456")
                 ,new User(3,"李四","156")};
         return users[id-1];
     }
 }

image.gif

2.先指定访问v1.0版本,启动

@Reference(version = "v1.0") 
 private UserService userService;

image.gif

控制台打印v1.0版本

image.gif

3.指定访问v2.0版本,重启dubbo-web(不需要重启dubbo-service了)

@Reference(version = "v1.0") 
 private UserService userService;

image.gif

image.gif

6.负载均衡

负载均衡策略:

1. Random :按权重随机,默认值。按权重设置随机概率。

2. RoundRobin:按权重轮询。

3. LeastActive:最少活跃调用数,相同活跃数的随机。

4. ConsistentHash: 一致性Hash,相同参数的请求总是发到同一提供者。

以默认的Random为例

1.启动 weight = 100 tomcat端口9000 dubbo端口20880 qos端口22222

@Service(weight = 100)
 public class UserServiceImpl implements UserService {
     @Override
     public String demo() {
         return "1......";
     }
 }

image.gif

<debbo:protocol port="20880"/>
 <dubbo:application name="dubbo-service">
    <dubbo:parameter key="qos.port" value="22222"/>
 </dubbo:application>

image.gif

2. 启动weight = 200 tomcat端口9001 dubbo端口20882 qos端口44444 再启动一次tomcat7:run

(注意不是重启上一个而是再启动一个)

@Service(weight = 200)
 public class UserServiceImpl implements UserService {
     @Override
     public String demo() {
         return "2......";
     }
 }

image.gif

<debbo:protocol port="20882"/>
 <dubbo:application name="dubbo-service">
         <dubbo:parameter key="qos.port" value="44444"/>
     </dubbo:application>

image.gif

3. 启动weight = 100 tomcat端口9002 dubbo端口20883 qos端口55555 再启动一次tomcat7:run

@Service(weight = 100)
 public class UserServiceImpl implements UserService {
     @Override
     public String demo() {
         return "3......";
     }
 }

image.gif

<debbo:protocol port="20883"/>
 <dubbo:application name="dubbo-service">
    <dubbo:parameter key="qos.port" value="55555"/>
 </dubbo:application>

image.gif

配置负载均衡的策略random

@Reference(loadbalance = "random" )

image.gif

启动dubbo-web模块的tomcat7:run

(我们一个启动了四个tomcat)

访问出现2 说明是第二个服务提供方

image.gif

不断刷新出现3 说明是第三个服务提供方

image.gif

不断刷新出现1 说明是第一个服务提供方

image.gif

7.集群容错

集群容错策略:

1. Failover Cluster:失败重试。(默认值)当出现失败,重试其它服务器,默认重试2次,使用

retries配置。一般用于读操作

2. Failfast Cluster : 快速失败,只发起一次调用,失败立即报错。通常用于写操作。

3. Failsafe Cluster : 失败安全,出现异常时,直接忽略。返回一个空结果。

4. FailbackCluster : 失败自动恢复,后台记录失败请求,定时重发。

5. Forking Cluster : 并行调用多个服务器,只要一个成功即返回。Broadcast Cluster :广播调用

有提供者,逐个调用,任意一台报错则报错。

以Failover Cluster策略为例

1.启动 tomcat端口9000 dubbo端口20880 qos端口22222

@Service()
 public class UserServiceImpl implements UserService {
      @Override
     public User findUserById(int id) {
         System.out.println(1);
         try {
             Thread.sleep(3000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         User[]users = {new User(1,"雪月清","123")
                 ,new User(2,"张三","456")
                 ,new User(3,"李四","156")};
         return users[id-1];
     }
 }

image.gif

<debbo:protocol port="20880"/>
 <dubbo:application name="dubbo-service">
    <dubbo:parameter key="qos.port" value="22222"/>
 </dubbo:application>

image.gif

2. tomcat端口9001 dubbo端口20881 qos端口44444 再启动一次tomcat7:run

@Service()
 public class UserServiceImpl implements UserService {
      @Override
     public User findUserById(int id) {
         System.out.println(2);
         try {
             Thread.sleep(3000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         User[]users = {new User(1,"雪月清","123")
                 ,new User(2,"张三","456")
                 ,new User(3,"李四","156")};
         return users[id-1];
     }
 }

image.gif

<debbo:protocol port="20881"/>
 <dubbo:application name="dubbo-service">
         <dubbo:parameter key="qos.port" value="44444"/>
     </dubbo:application>

image.gif

3. tomcat端口9002 dubbo端口20882 qos端口55555 再启动一次tomcat7:run

@Service()
 public class UserServiceImpl implements UserService {
      @Override
     public User findUserById(int id) {
         System.out.println(3);  
         User[]users = {new User(1,"雪月清","123")
                 ,new User(2,"张三","456")
                 ,new User(3,"李四","156")};
         return users[id-1];
     }
 }

image.gif

<debbo:protocol port="20882"/>
 <dubbo:application name="dubbo-service">
    <dubbo:parameter key="qos.port" value="55555"/>
 </dubbo:application>

image.gif

访问成功!

image.gif

但是dubbo-web模块的tomcat日志信息出现超时错误,

三个服务提供方的日志信息

image.gif

image.gif

image.gif

发现三个都访问了,但是1和2都会超时(我们通过进程睡眠模拟了超时),消费方会访问1超时,

然后根据Failover Cluster集群容错策略,重试访问2也超时了,再重试一次访问3成功!

8.服务降级

mock=force:return null 表示消费方对该服务的方法调用都直接返回null值,不发起远程调用。用

来屏蔽不重要服务不可用时对调用方的影响。

1.配置服务提供方

@Service()
 public class UserServiceImpl implements UserService {
  @Override
 public User findUserById(int id) {
     System.out.println(3);  
     User[]users = {new User(1,"雪月清","123")
             ,new User(2,"张三","456")
             ,new User(3,"李四","156")};
     return users[id-1];
 } 
 }

image.gif

2.配置服务消费方

@Reference(mock = "force:return null")

image.gif

3.分别启动服务提供方和服务消费方

image.gif

成为了空白页面,服务被屏蔽了

mock=fail:return null 表示消费方对该服务的方法调用在失败后,再返回null值,不抛异常。用来

容忍不重要服务不稳定时对调用方的影响。

修改服务消费方的配置其余不变重新启动

@Reference(mock = "fail:return null")

image.gif

image.gif

(服务提供方我们模拟了超时)失败后重试了三次,但是页面看不到任何信息

image.gif


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
相关文章
|
存储 缓存 算法
分布式锁服务深度解析:以Apache Flink的Checkpointing机制为例
【10月更文挑战第7天】在分布式系统中,多个进程或节点可能需要同时访问和操作共享资源。为了确保数据的一致性和系统的稳定性,我们需要一种机制来协调这些进程或节点的访问,避免并发冲突和竞态条件。分布式锁服务正是为此而生的一种解决方案。它通过在网络环境中实现锁机制,确保同一时间只有一个进程或节点能够访问和操作共享资源。
479 3
|
9月前
|
消息中间件 人工智能 监控
文生图架构设计原来如此简单之分布式服务
想象一下,当成千上万的用户同时要求AI画图,如何公平高效地处理这些请求?文生图/图生图大模型的架构设计看似复杂,实则遵循简单而有效的原则:合理排队、分工明确、防患未然。
362 14
文生图架构设计原来如此简单之分布式服务
|
12月前
|
SpringCloudAlibaba 负载均衡 Dubbo
【SpringCloud Alibaba系列】Dubbo高级特性篇
本章我们介绍Dubbo的常用高级特性,包括序列化、地址缓存、超时与重试机制、多版本、负载均衡。集群容错、服务降级等。
1815 7
【SpringCloud Alibaba系列】Dubbo高级特性篇
|
11月前
|
SQL 分布式计算 DataWorks
MaxCompute MaxFrame评测 | 分布式Python计算服务MaxFrame(完整操作版)
在当今数字化迅猛发展的时代,数据信息的保存与分析对企业决策至关重要。MaxCompute MaxFrame是阿里云自研的分布式计算框架,支持Python编程接口、兼容Pandas接口并自动进行分布式计算。通过MaxCompute的海量计算资源,企业可以进行大规模数据处理、可视化数据分析及科学计算等任务。本文将详细介绍如何开通MaxCompute和DataWorks服务,并使用MaxFrame进行数据操作。包括创建项目、绑定数据源、编写PyODPS 3节点代码以及执行SQL查询等内容。最后,针对使用过程中遇到的问题提出反馈建议,帮助用户更好地理解和使用MaxFrame。
|
11月前
|
SQL 分布式计算 数据处理
云产品评测|分布式Python计算服务MaxFrame | 在本地环境中使用MaxFrame + 基于MaxFrame实现大语言模型数据处理
本文基于官方文档,介绍了由浅入深的两个部分实操测试,包括在本地环境中使用MaxFrame & 基于MaxFrame实现大语言模型数据处理,对步骤有详细说明。体验下来对MaxCompute的感受是很不错的,值得尝试并使用!
288 1
|
11月前
|
分布式计算 数据处理 MaxCompute
云产品评测|分布式Python计算服务MaxFrame
云产品评测|分布式Python计算服务MaxFrame
232 2
|
11月前
|
人工智能 分布式计算 数据处理
有奖评测,基于分布式 Python 计算服务 MaxFrame 进行数据处理
阿里云MaxCompute MaxFrame推出分布式Python计算服务MaxFrame评测活动,助力开发者高效完成大规模数据处理、可视化探索及ML/AI开发。活动时间为2024年12月17日至2025年1月31日,参与者需体验MaxFrame并发布评测文章,有机会赢取精美礼品。
|
消息中间件 存储 安全
分布式系统架构3:服务容错
分布式系统因其复杂性,故障几乎是必然的。那么如何让系统在不可避免的故障中依然保持稳定?本文详细介绍了分布式架构中7种核心的服务容错策略,包括故障转移、快速失败、安全失败等,以及它们在实际业务场景中的应用。无论是支付场景的快速失败,还是日志采集的安全失败,每种策略都有自己的适用领域和优缺点。此外,文章还为技术面试提供了解题思路,助你在关键时刻脱颖而出。掌握这些策略,不仅能提升系统健壮性,还能让你的技术栈更上一层楼!快来深入学习,走向架构师之路吧!
317 12
|
人工智能 分布式计算 数据处理
云产品评测:MaxFrame — 分布式Python计算服务的最佳实践与体验
阿里云推出的MaxFrame是一款高性能分布式计算平台,专为大规模数据处理和AI应用设计。它提供了强大的Python编程接口,支持分布式Pandas操作,显著提升数据处理速度(3-5倍)。MaxFrame在大语言模型数据处理中表现出色,具备高效内存管理和任务调度能力。然而,在开通流程、API文档及功能集成度方面仍有改进空间。总体而言,MaxFrame在易用性和计算效率上具有明显优势,但在开放性和社区支持方面有待加强。
201 9
|
12月前
|
分布式计算 数据处理 MaxCompute
分布式Python计算服务MaxFrame使用心得
大家好,我是V哥。MaxFrame是阿里云自研的分布式计算框架,专为Python开发者设计,支持大规模数据处理和AI模型开发。MaxFrame适用于快速进行数据处理、数据科学和交互式探索,支持按量付费及包年包月两种计费方式。通过两个案例(金融数据清洗和大语言模型预处理),展示了MaxFrame在大规模数据处理中的显著性能提升。安装MaxFrame客户端只需简单几步,轻松开启高效数据处理之旅。欢迎关注威哥爱编程,一起交流技术心得!
182 0