Dubbo生态之dubbo功能

1.Dubbo生态功能的思考

        dubbo具有哪些功能呢?我们要根据dubbo的架构和本质是用来干什么的来思考?

        首先对于分布式微服务,假设我们有两个服务A和B,并且都是集群部署的。那么按照我们正常的流程应该是启动两个微服务项目(启动时应该做什么呢? 检查、注册发布、版本支持、协议);

        其次我们服务进行了集群部署,并且接口注册到了注册中心中。那么我们的消费者如何订阅到集群中的哪一个服务呢?如果网络通信中出现了错误怎么办呢?(负载均衡、容错机制、服务降级)

        再其次我们找到了服务接口,那么我们使用该接口的调用方式是什么呢?(异步调用,泛化调用)

        最后我们调用到了接口服务,那么接口的传参呢,应该怎么定义,以一种什么样的形式进行网络通信呢?参数需不需要做校验?(请求参数校验、调用链路隐式传参、Kryo和FST序列化)

2. 微服务启动

2.1 启动时检查

在dubbo服务中,难免会出现循环依赖的情况

而Dubbo在启动的时候,会默认去检查依赖的服务状态,并且简历通信连接,因此在这种情况下,就会导致服务无法启动。

Dubbo里面提供了一个check参数,可以通过这个参数来关闭启动检查,等用到的时候再进行检查

@RestController
public class UserController {// 在启动的时候就不会检查userService该服务@DubboReference(check = false)IUserService userService;@GetMapping("/coupon")public String validCoupons(){return userService.selectValidTemplates();}}

dubbo.consumer.check=false  关闭消费端所有服务的启动检查

dubbo.registry.check=false 关闭注册中心启动时检查

2.2  服务接口的版本支持

当我们在进行功能迭代的时候,就会可能存在新的功能对老版本不兼容的时候,因此这时候,我们就可以通过版本号来过渡,每次服务启动发布都是一个新的版本。

配置方式如下:

@DubboService(registry = {"zk-registry","nacos-registry"},version =
"1.0")
public class UserService implements IUserService {
@Override
public String say(String msg) {
return "Spring Boot Integration Apache Dubbo Example";
}
}

消费端消费的时候,也可以在@DubboReference上指定消费的版本号

@RestController
public class UserController {@DubboReference(version = "1.0")IUserService userService;@GetMapping("/say")public String say(){return userService.say("Mic");}
}

2.3 多协议支持

dubbo进行多协议发布的配置

dubbo.protocols.tri.name = tri

dubbo.protocols.tri.port = -1

dubbo.protocols.tri.id = tri

dubbo.protocols.dubbo.name = dubbo

dubbo.protocols.dubbo.port = -1

dubbo.protocols.dubbo.id = dubbo

添加注解信息 @DubboService(protocol={"dubbo","tri"})

2.4 服务的注册与发现

注册中心是dubbo生态的核心功能,对服务进行了一个统一的管理。当然dubbo也支持多注册中心注册,只需要配置时采用 registry={};即可

在dubbo3之前,都是面向RPC方法去定义服务的,但是这种方法有着很多的不足。

a.注册中心上存储的数据更多了,增加了数据推送的压力

b.业内主流的微服务模型都是基于应用纬度的服务注册发现。如果Dubbo要拥抱云原生,就必然需要和这些模型对齐。因此从Dubbo3开始,就增加了应用级别的服务注册发现,默认情况下,服务端会自动开启接口级和应用级的双重注册(为了兼容dubbo2.x版本)

# 双注册
dubbo.application.register-mode = all
# 仅应用级注册
dubbo.application.register-mode = instance
还可以通过注册中心地址上配置参数 registry-type=service 来显示指定该注册中心为应用级服务发现的注册中心,带上此配置的注册中心将只进行应用 级服务发现
dubbo.registry.address = "zookeeper : //192.168.8.133 : 2181?registry-type = service"

3. 如何找到集群服务接口

3.1 负载均衡策略

3.1.1  权重随机算法

假设我们有一组服务器 servers = [A, B, C],他们对应的权重为 weights =[5, 3, 2],权重总和为10。
现在把这些权重值平铺在一维坐标值上,
[0, 5) 区间属于服务器 A,
[5, 8) 区间属于服务器 B,
[8, 10) 区间属于服务器 C。
接下来通过随机数生成器生成一个范围在 [0, 10) 之间的随机数,然后计算这个随机数会落到哪个区间上。
比如数字3会落到服务器 A 对应的区间上,此时返回服务器 A 即可。

3.1.2  加权轮询算法

加权轮询就是轮流分配,但是我们并不能保证每台服务器的性能都是相近的,因此我们应采用加权轮询的方式

比如服务器 A、B、C 权重比为 5:2:1。那么在8次请求中,服务器 A 将收到其中的5次请求,服务器 B 会收到其中的2次请求,服务器 C 则收到其中的1次请求

3.1.3  一致性hash算法

简单来说,一致性hash算法就是一个hash圆环,假设服务器先根据ip和端口计算出的hash值在圆环上的位置,则dubbo中是根据传参来确定hash值的,因此一致性hash算法就是根据对象的传参计算出该对象的hash值,然后顺时针旋转,先到达哪台服务器就请求哪台服务器

3.1.4 最少活跃调用算法

最少活跃调用数算法,活跃调用数越小,表明该服务提供者效率越高,单位时间内可处理更多的请求这个是比较科学的负载均衡算法。
每个服务提供者对应一个活跃数 active。初始情况下,所有服务提供者活跃数均为0。每收到一个请求,活跃数加1,完成请求后则将活跃数减1。在服 务运行一段时间后,性能好的服务提供者处理请求的速度更快,因此活跃数 下降的也越快,此时这样的服务提供者能够优先获取到新的服务请求

3.1.5 最短响应时间负载均衡算法

筛选成功调用响应时间最短的调用程序的数量,并计算这些调用程序的权重和数量。然后根据响应时间的长短来分配目标服务的路由权重

3.2 容错机制

@DubboService(cluster = "failfast")

3.2.1 Failover Cluster(默认)

失败自动切换,当出现失败,重试其它服务器。通常用于读操作,单重试会带来更长延迟。可通过retries=“2”来设置重试次数(不含第一次)

3.2.2 Failfast Cluster 

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

3.2.3 Failsafe Cluster

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

3.2.4 Fallback Cluster

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

3.2.5 Forking Cluster

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

3.2.6 Broadcast Cluster

广播调用所有提供者,逐个调用,任意一台报错则报错。(2.1.0开始支持)
通常用于通知所有提供者更新缓存或日志等本地资源信息。

3.2.7 Available Cluster

调用目前可用的实例(只调用一个),如果当前没有可用的实例,则抛出异常。
通常用于不需要负载均衡的场景。

3.2.8 Mergeable Cluster

将集群中的调用结果聚合起来返回结果,通常和group一起配合使用。通过分组对结果进行聚合并返回聚合后的结果,比如菜单服务,用group区分同一接口的多种实现,现在消费方需从每种group中调用一次并返回结果,对结果进行合并之后返回,这样就可以实现聚合菜单项。

注意: 在实际应用中 查询语句容错策略建议使用默认Failover Cluster, 而增删改建议使用 Failfast Cluster或者使用 Failover Cluster(retries="0") 策略  防止出现数据重复添加等等其它问题!建议在设计接口时候把查询接口方法单独做一个接口提供查询

3.3 服务降级

服务降级是一种策略,dubbo中提供了一个mock的配置,可以实现当服务提供方出现网络异常或者挂掉以后,客户端不抛出异常,而是通过Mock数据返回自定义的数据。主要有几种方式

1. 对一些非核心服务进行人工降级,在大促之前通过降级开关关闭哪些推荐内容、评价等对主流程没有影响的功能
2. 故障降级,比如调用的远程服务挂了,网络故障、或者RPC服务返回异常。 那么可以直接降级,降级的方案比如设置默认值、采用兜底数据(系统推荐的行为广告挂了,可以提前准备静态页面做返回)等等
3. 限流降级,在秒杀这种流量比较集中并且流量特别大的情况下,因为突发访问量特别大可能会导致系统支撑不了。这个时候可以采用限流来限制访问量。当达到阀值时,后续的请求被降级,比如进入排队页面,比如跳转到错误页(活动太火爆,稍后重试等)

4. 服务的调用方式

4.1 异步调用

dubbo实现异步调用主要是通过async这个属性来实现的。

代码举例:

@RestController
public class UserController {@DubboReference(async = true,timeout = 5000)IUserService userService;@GetMapping("/say")public String say() throws ExecutionException,InterruptedException {String rs=userService.say("Mic");System.out.println(Thread.currentThread().getName()+",非阻塞执行后续逻辑");CompletableFuture<String> userFuture=              RpcContext.getServerContext().getCompletableFuture();CompletableFuture<String> future=userFuture.whenComplete((v,e)->{if(e==null){System.out.println(Thread.currentThread().getName()+":正常收到处理返回结                果:"+v);}else{e.printStackTrace();}});System.out.println(Thread.currentThread().getName()+":不等待异步返回,继续执行后续代码");return "调用成功";
}

4.2 泛化调用

泛化调用是指服务端的服务没有遵循api模块,那么dubbo可以调用吗,可以的。只要知道接口的路径和方法名,dubbo中可以通过genericService进行泛化调用

@RestController
public class GenericController {@DubboReference(interfaceName = "zsc.com.cn.user.IUserService")GenericService genericService;@GetMapping("/generic")public String generic(){Map<String,Object> person=new HashMap<>();person.put("name","ZSC");person.put("age",18);Object result=genericService.$invoke("savePerson",new String[]{"zsc.com.cn.user.Person"},new Object[]{person});return result.toString();}
}

5.  接口调用传参

5.1 请求参数校验

a.引入4个jar包

        <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>8.0.0.Final</version></dependency><dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId></dependency><dependency><groupId>javax.el</groupId><artifactId>javax.el-api</artifactId><version>3.0.0</version></dependency><dependency><groupId>org.glassfish</groupId><artifactId>javax.el</artifactId><version>3.0.0</version></dependency>

b.请求参数增加注解

@Data
public class CouponDto implements Serializable {private static final long serialVersionUID = -1L;@NotNull@Size(min=1,max = 20)private String name;@Min(1)@Max(1000)private int num;}

5.2 调用链路隐式传参

可以通过RpcContext上的setAttachment和getAttachment在服务消费方和提供方之间进行 参数的隐式传递

RpcContext是一个ThreadLocal的临时状态记录器,可以获取服务端或者消费端的上下文信息

具体用法

在服务端写入,RpcContext.getServerContext.setAttachment(k,v);
在服务端读取,RpcContext.getServerAttachment.getAttachment(k);
在消费端写入,RpcContext.getClientAttachment.setAttachment(k,v);
在消费端读取,RpcContext.getServerContext().getAttachment("result");

5.3 Kryo和FST序列化

        序列化是远程通信过程中所对参数进行的一种操作方式,使得该参数经过序列化后能够进行网络通信,因此序列化对于远程调用的响应速度、吞吐量、网络带宽等消耗起着至关重要的作用。

目前最高效的针对java而设计的两种序列化方式是Kryo和FST,如何使用?

引入jar包,加一个配置即可

<dependency>
<groupId> org.apache.dubbo.extensions </groupId>
<artifactId> dubbo-serialization-kryo </artifactId>
<version> 1.0.0 </version>
</dependency>
<dependency>
<groupId> org.apache.dubbo.extensions </groupId>
<artifactId> dubbo-serialization-fst </artifactId>
<version> 1.0.0 </version>
</dependency>

针对指定协议配置序列化的方式

dubbo.protocol.name = dubbo
dubbo.protocol.serialization = kryo

6. 调用信息的记录

在dubbo3日志分为日志适配和访问日志,如果想记录每一次请求信息,可以开启访问日志,类似于apache的访问日志

使用方法有两种

a.直接设置dubbo.protocol.accesslog=true,表示输出到应用的log4j日志

b.输出到指定文件 dubbo.protocol.accesslog=/log/access.log

7.总结

        本文从一个RPC的工作流程和中间需要进行的安全保障,交互形式,请求方式等出发,对dubbo生态的功能进行了一个简单的概况,从服务启动、发布到被消费者调用的整个远程通信过程中涉及到的点, dubbo都有着一系列的功能支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/329163.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vscode添加代办相关插件,提高开发效率

这里写目录标题 前言插件添加添加TODO Highlight安装TODO Highlight在项目中自定义需要高亮显示的关键字 TODO Tree安装TODO Tree插件 单行注释快捷键 前言 在前端开发中&#xff0c;我们经常会遇到一些未完成、有问题或需要修复的部分&#xff0c;但又暂时未完成或未确定如何处…

C++初阶学习第十弹——探索STL奥秘(五)——深入讲解vector的迭代器失效问题

vector&#xff08;上&#xff09;&#xff1a;C初阶学习第八弹——探索STL奥秘&#xff08;三&#xff09;——深入刨析vector的使用-CSDN博客 vector&#xff08;中&#xff09;&#xff1a;C初阶学习第九弹——探索STL奥秘&#xff08;四&#xff09;——vector的深层挖掘和…

MYSQL 集群

1.集群目的:负载均衡 解决高并发 高可用HA 服务可用性 远程灾备 数据有效性 类型:M M-S M-S-S M-M M-M-S-S 原理:在主库把数据更改(DDL DML DCL&#xff09;记录到二进制日志中。 备库I/O线程将主库上的日志复制到自己的中继日志中。 备库SQL线程读取中继日志…

Mongodb介绍及springboot集成增删改查

文章目录 1. MongoDB相关概念1.1 业务应用场景1.2 MongoDB简介1.3 体系结构1.4 数据模型1.5 MongoDB的特点 2. docker安装mongodb3. springboot集成3.1 文件结构3.2 增删改查3.2.1 增加insert3.2.2 保存save3.2.3 更新update3.2.4 查询3.2.5 删除 1. MongoDB相关概念 1.1 业务…

【学习笔记】Windows GDI绘图(五)图形路径GraphicsPath详解(上)

文章目录 图形路径GraphicsPath填充模式FillMode构造函数GraphicsPath()GraphicsPath(FillMode)GraphicsPath(Point[],Byte[])和GraphicsPath(PointF[], Byte[])GraphicsPath(Point[], Byte[], FillMode)和GraphicsPath(PointF[], Byte[], FillMode)PathPointType 属性FillMode…

jsp连接数据库

1.打开命令框进入数据库 打开eclipse创建需要连接的项目 粘贴驱动程序 查看驱动器 使用sql的包 int代表个 conlm代表列名 <%page import"java.sql.ResultSet"%> <%page import"java.sql.Statement"%> <%page import"java.sql.Connect…

关于如何创建一个可配置的 SpringBoot Web 项目的全局异常处理

前情概要 这个问题其实困扰了我一周时间&#xff0c;一周都在 Google 上旅游&#xff0c;我要如何动态的设置 RestControllerAdvice 里面的 basePackages 以及 baseClasses 的值呢&#xff1f;经过一周的时间寻求无果之后打算决定放弃的我终于找到了一些关键的线索。 当然在此…

html5 笔记01

01 表单类型和属性 input的type属性 单行文本框: typetext 电子邮箱 : typeemail 地址路径 : type url 定义用于输入数字的字段: typenumber 手机号码: typetel 搜索框 : typesearch 定义颜色选择器 : typecolor 滑块控件 : typerange 定义日期 :typedate 定义输入时间的控件…

CR80清洁卡都能用在什么地方?

CR80清洁卡&#xff08;也被称为ISO 7810 ID-1清洁卡&#xff09;的规格确实使其在各种需要读取磁条或接触式智能卡的设备中都有广泛的用途。这些设备包括但不限于&#xff1a; ATM自动终端机&#xff1a;当ATM机的磁条读卡器出现故障或读卡不灵敏时&#xff0c;可以使用CR80清…

第三期【数据库主题文档上传激励活动】已开启!快来上传文档赢奖励

2023年9月、11月&#xff0c;墨天轮社区相继举办了第一期与第二期【数据库主题文档上传激励活动】&#xff0c;众多用户积极参与、上传了大量优质的数据库主题干货文档&#xff0c;在记录经验的同时也为其他从业者带来了参考帮助&#xff0c;这正实现了“乐知乐享、共同成长”的…

以及Spring中为什么会出现IOC容器?@Autowired和@Resource注解?

以及Spring中为什么会出现IOC容器&#xff1f;Autowired和Resource注解&#xff1f; IOC容器发展史 没有IOC容器之前 首先说一下在Spring之前&#xff0c;我们的程序里面是没有IOC容器的&#xff0c;这个时候我们如果想要得到一个事先已经定义的对象该怎么得到呢&#xff1f;…

STM32自己从零开始实操02:输入部分原理图

一、触摸按键 1.1指路 项目需求&#xff1a; 4个触摸按键&#xff0c;主控芯片 TTP224N-BSBN&#xff08;嘉立创&#xff0c;封装 TSSOP-16&#xff09;&#xff0c;接入到 STM32 的 PE0&#xff0c;PE1&#xff0c;PE2&#xff0c;PE3。 1.2走路 1.2.1数据手册重要信息提…

AI--构建检索增强生成 (RAG) 应用程序

LLM 所实现的最强大的应用之一是复杂的问答 (Q&A) 聊天机器人。这些应用程序可以回答有关特定源信息的问题。这些应用程序使用一种称为检索增强生成 (RAG) 的技术。 典型的 RAG 应用程序有两个主要组件 索引&#xff1a;从源中提取数据并对其进行索引的管道。这通常在线下…

CTFshow之文件上传web入门151关-161关解密。包教包会!!!!

这段时间一直在搞文件上传相关的知识&#xff0c;正好把ctf的题目做做写写给自字做个总结&#xff01; 不过有一个确定就是所有的测试全部是黑盒测试&#xff0c;无法从代码层面和大家解释&#xff0c;我找个时间把upload-labs靶场做一做给大家讲讲白盒的代码审计 一、实验准…

保研笔试复习——nju

文章目录 一、单选计算机网络计算机组成原理数字逻辑电路数据结构操作系统微机系统 多选题计算机网络计算机系统结构操作系统 免责声明&#xff1a;题目源自于网络&#xff0c;侵删。 就在今天2024-5-18&#xff0c;考的题下面的只有一道AVL的原题&#xff0c;其他都不是原题&a…

【C++初阶】--- C++入门(上)

目录 一、C的背景及简要介绍1.1 什么是C1.2 C发展史1.3 C的重要性 二、C关键字三、命名空间2.1 命名空间定义2.2 命名空间使用 四、C输入 & 输出 一、C的背景及简要介绍 1.1 什么是C C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&…

Docker Hub注册及上传自定义镜像

说明&#xff1a;本文介绍如何注册Docker Hub&#xff0c;及将自己自定义镜像上传到Docker Hub上&#xff1b; 注册Docker Hub 浏览器输入&#xff1a;http://hub.docker.com/&#xff0c;进入Docker Hub官网 注&#xff1a;如果无法访问&#xff0c;可在GitHub上下载一个Ste…

全面掌握深度学习:从基础到前沿

引言&#xff1a;深入探索深度学习的世界 在人工智能&#xff08;AI&#xff09;的广阔领域中&#xff0c;深度学习已经成为最令人瞩目的技术之一。它不仅推动了科技的许多突破性进展&#xff0c;也正在改变我们的工作和生活方式。本博客旨在全面总结深度学习的关键知识点&…

分类和品牌关联

文章目录 1.数据库表设计1.多表关联设计2.创建表 2.使用renren-generator生成CRUD1.基本配置检查1.generator.properties2.application.yml 2.生成代码1.进入localhost:81生成代码2.将main目录覆盖sunliving-commodity模块的main目录 3.代码检查1.注释掉CategoryBrandRelationC…

Map遍历、反射、GC

map的遍历 用foreach遍历 HashMap<Character,Integer> map new HashMap<>();map.put(A,2);map.put(B,3);map.put(C,3);for (Map.Entry<Character,Integer> entry: map.entrySet()) {char key entry.getKey();int value entry.getValue();System.out.prin…