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

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
传统型负载均衡 CLB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
简介: 本文详细介绍并实际操作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


相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
3月前
|
Java 数据库
在Java中使用Seata框架实现分布式事务的详细步骤
通过以上步骤,利用 Seata 框架可以实现较为简单的分布式事务处理。在实际应用中,还需要根据具体业务需求进行更详细的配置和处理。同时,要注意处理各种异常情况,以确保分布式事务的正确执行。
|
3月前
|
消息中间件 Java Kafka
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
|
2月前
|
存储 监控 数据可视化
常见的分布式定时任务调度框架
分布式定时任务调度框架用于在分布式系统中管理和调度定时任务,确保任务按预定时间和频率执行。其核心概念包括Job(任务)、Trigger(触发器)、Executor(执行器)和Scheduler(调度器)。这类框架应具备任务管理、任务监控、良好的可扩展性和高可用性等功能。常用的Java生态中的分布式任务调度框架有Quartz Scheduler、ElasticJob和XXL-JOB。
426 66
|
7天前
|
Dubbo 应用服务中间件 API
使用 Apifox、Postman 测试 Dubbo 服务,Apache Dubbo OpenAPI 即将发布
Apache Dubbo 3.3.3(即将发布)实现了与 OpenAPI 的深度集成,通过与 OpenAPI 的深度集成,用户能够体验到从文档生成到接口调试、测试和优化的全流程自动化支持。不论是减少手动工作量、提升开发效率,还是支持多语言和多环境,Dubbo 3.3.3 都展现了其对开发者体验的极大关注。结合强大的 Mock 数据生成和自动化测试能力,这一版本为开发者提供了极具竞争力的服务治理解决方案。如果你正在寻找高效、易用的微服务框架,Dubbo 3.3.3 将是你不容错过的选择。
|
29天前
|
数据采集 人工智能 分布式计算
MaxFrame:链接大数据与AI的高效分布式计算框架深度评测与实践!
阿里云推出的MaxFrame是链接大数据与AI的分布式Python计算框架,提供类似Pandas的操作接口和分布式处理能力。本文从部署、功能验证到实际场景全面评测MaxFrame,涵盖分布式Pandas操作、大语言模型数据预处理及企业级应用。结果显示,MaxFrame在处理大规模数据时性能显著提升,代码兼容性强,适合从数据清洗到训练数据生成的全链路场景...
76 5
MaxFrame:链接大数据与AI的高效分布式计算框架深度评测与实践!
|
18天前
|
人工智能 分布式计算 大数据
MaxFrame 产品评测:大数据与AI融合的Python分布式计算框架
MaxFrame是阿里云MaxCompute推出的自研Python分布式计算框架,支持大规模数据处理与AI应用。它提供类似Pandas的API,简化开发流程,并兼容多种机器学习库,加速模型训练前的数据准备。MaxFrame融合大数据和AI,提升效率、促进协作、增强创新能力。尽管初次配置稍显复杂,但其强大的功能集、性能优化及开放性使其成为现代企业与研究机构的理想选择。未来有望进一步简化使用门槛并加强社区建设。
50 7
|
3月前
|
存储 Java 关系型数据库
在Spring Boot中整合Seata框架实现分布式事务
可以在 Spring Boot 中成功整合 Seata 框架,实现分布式事务的管理和处理。在实际应用中,还需要根据具体的业务需求和技术架构进行进一步的优化和调整。同时,要注意处理各种可能出现的问题,以保障分布式事务的顺利执行。
197 53
|
2月前
|
消息中间件 存储 安全
分布式系统架构3:服务容错
分布式系统因其复杂性,故障几乎是必然的。那么如何让系统在不可避免的故障中依然保持稳定?本文详细介绍了分布式架构中7种核心的服务容错策略,包括故障转移、快速失败、安全失败等,以及它们在实际业务场景中的应用。无论是支付场景的快速失败,还是日志采集的安全失败,每种策略都有自己的适用领域和优缺点。此外,文章还为技术面试提供了解题思路,助你在关键时刻脱颖而出。掌握这些策略,不仅能提升系统健壮性,还能让你的技术栈更上一层楼!快来深入学习,走向架构师之路吧!
71 11
|
2月前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
94 2
|
3月前
|
数据库
如何在Seata框架中配置分布式事务的隔离级别?
总的来说,配置分布式事务的隔离级别是实现分布式事务管理的重要环节之一,需要认真对待和仔细调整,以满足业务的需求和性能要求。你还可以进一步深入研究和实践 Seata 框架的配置和使用,以更好地应对各种分布式事务场景的挑战。
109 41