dubbo
Posted 穷少年
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dubbo相关的知识,希望对你有一定的参考价值。
文章目录
dubbo是什么?
- Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和Spring框架无缝集成。
- Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
Dubbo 架构
上述节点简单说明:
- Provider 暴露服务的服务提供方
- Consumer 调用远程服务的服务消费方
- Registry 服务注册与发现的注册中心
- Monitor 统计服务的调用次数和调用时间的监控中心
- Container 服务运行容器
调用关系说明: 1. 服务容器负责启动,加载,运行服务提供者。 2. 服务提供者在启动时,向注册中心注册自己提供的服务。 3. 服务消费者在启动时,向注册中心订阅自己所需的服务。 4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
我们在讲 Dubbo 的时候提到了 Dubbo 实际上是一款 RPC 框架,那么RPC 究竟是什么呢?相信看了下面我对 RPC 的介绍你就明白了!
什么是 RPC?
RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。比如两个不同的服务A,B部署在两台不同的机器上,那么服务 A 如果想要调用服务 B 中的某个方法该怎么办呢?使用 HTTP请求 当然可以,但是可能会比较慢而且一些优化做的并不好。 RPC 的出现就是为了解决这个问题。
dubbo官方中文文档
dubbo-admin的下载安装
dubbo-admin 是dubbo的管理界面平台,且是一个前后端分离的项目,前端使用vue,后端使用springboot。
-
下载
dubbo-admin是在github上发布的项目源码,所以我只需要前往github下载即可
github地址:https://github.com/apache/dubbo-admin
-
运行项目
- dubbo-admin是一个前后端分离项目,所以我们需要分别启动后端服务器和前端程序
- 在启动后端服务之前,需要在在
dubbo-admin-server/src/main/resources/application.properties
中指定注册中心地址(注册中心一般推荐使用zookeeper) - 前端项目启动:进入dubbo-admin-ui文件夹中,运行
npm run dev
即可启动
-
启动成功访问给出的访问地址
密码用户名默认都是root
dubbo+springboot快速入门
以前我们的项目全部代码都是放到同一台服务器上运行的单机模式,现在系统模块拆分,并部署到各个服务器上运行,并使用dubbo来作为服务中介
1.使用zookeeper来作为注册中心
如何使用zookeeper具体请看这篇文章:zookeeper的安装与使用
2.搭建公共接口(API)模块
公共模块里面,存放接口,与实体类(需要实现序列化),采用maven项目实现,以便后续项目的使用
DemoService
public interface DemoService
public String sayHello();
public User getUser();
User
因为dubbo是一个远程服务调用框架,在服务之前调用,要想传输类对象,这个实体类就必须实现序列化(Serializable ),这也是dubbo一大高级特性
public class User implements Serializable
private Integer id;
private String name;
private Double score;
public User()
public User(Integer id, String name, Double score)
this.id = id;
this.name = name;
this.score = score;
public Integer getId()
return id;
public void setId(Integer id)
this.id = id;
public String getName()
return name;
public void setName(String name)
this.name = name;
public Double getScore()
return score;
public void setScore(Double score)
this.score = score;
使用 mvn install
命令将这个项目安装到本地的maven仓库
3.搭建服务提供者(provider)
- 创建springboot项目,取名为provider
- 导入相应的坐标
<dependencies>
<!--将第一步创建的公共模块导入进来-->
<dependency>
<groupId>org.example</groupId>
<artifactId>api_simple</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--spring boot starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.5.2</version>
</dependency>
<!--dubbo springboot集成依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<!--Curator是一个比较完善的ZooKeeper客户端框架,通过封装的一套高级API 简化了ZooKeeper的操作-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.1.0</version>
<exclusions>
<!--因为springboot本身自带sl4j日志,所以我们不需要log4j-->
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
- 编写application.properties文件
# 告诉注册中心,你的项目的名称,具有唯一性
dubbo.application.name=provider
# 告诉程序你的注册中心的地址,端口号,以及所使用的的协议,我们使用zookeeper作为注册中心,那么协议就是zookeeper
dubbo.registry.address=zookeeper://192.168.23.135:2181
# 下面这个配置使用为了防止,在第一次注册的时候,由于timeout时间过短导致的连接失败的情况
dubbo.config-center.timeout=10000
dubbo.registry.timeout=10000
# 因为是服务端,我们需要让程序像服务器一样运行起来,那么我们就必须要给程序一个端口号
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
# 元数据配置,注册中心地址 如果不配则无法看见元数据
# 但是个人发现,这个配置写上去,就会报zookeeper not connected异常
# dubbo-springboot版本2.7.8不配置这一项,元数据一样会显示
# dubbo.metadata-report.address=zookeeper://127.0.0.1:2181
- 继承实现公共模块的接口,实现接口中的方法
// 1. 以前这里的注解是@Service
// 2. 作用是将UserServiceImpl生成bean对象并放入spring容器
// 3. @DubboService是将此服务信息(ip:port、服务名字),放在注册中心,提供给消费者。
@DubboService(interfaceClass = DemoService.class)
public class DemoServiceImpl implements DemoService
@Override
public String sayHello()
return "hello world";
@Override
public User getUser()
return new User(1,"zhangsan",99.9);
- 在springboot的启动类上添加@EnableDubbo注解,表示启动dubbo服务,如下:
- 打开dubbo Admin查看。
点击详情,可以具体看见详细信息,如ip、port、权重等等。
继续往下看,则可以看见元数据,是指服务里面具体的方法名,参数列表,返回值。
4.搭建服务消费者(consumer)
- 创建springboot工程,取名为consumer
- 导入相应jar包坐标。
<dependencies>
<!--公共模块的坐标-->
<dependency>
<groupId>org.example</groupId>
<artifactId>api_simple</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--spring boot starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.5.2</version>
</dependency>
<!--因为是消费者,调用者,所以我们的项目是一个web项目-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.5.2</version>
</dependency>
<!--dubbo springboot集成依赖-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<!--Curator是一个比较完善的ZooKeeper客户端框架,通过封装的一套高级API 简化了ZooKeeper的操作-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.1.0</version>
<exclusions>
<!--因为springboot本身自带sl4j日志,所以我们不需要log4j-->
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
- 编写application.properties属性文件
# 告诉注册中心,你的项目的名称,具有唯一性
dubbo.application.name=provider
# 告诉程序你的注册中心的地址,端口号,以及所使用的的协议,我们使用zookeeper作为注册中心,那么协议就是zookeeper
dubbo.registry.address=zookeeper://192.168.23.135:2181
# 下面这个配置使用为了防止,在第一次注册的时候,由于timeout时间过短导致的连接失败的情况
dubbo.config-center.timeout=10000
dubbo.registry.timeout=10000
# web项目的端口号
server.port=8888
4.编写web层
@RestController
public class DemoController
// DubboReference的作用是去注册中心寻找对应的服务,
// 并且生成代理对象,放入spring容器中,并赋值给demoService
@DubboReference
private DemoService demoService;
@RequestMapping("demo01")
public Object demo01()
return demoService.sayHello();
@RequestMapping("demo02")
public Object demo02()
return demoService.getUser();
- 同理,在springboot的启动类上添加@EnableDubbo注解,表示启动dubbo服务。
- 访问两个接口
到这里,我们的分布式小项目基本就完成了
5.源码地址
https://gitee.com/cn2770345524/test_dubbo02/
参考文章:
dubbo的高级特性
1.对象序列化
dubbo框架是一个远程调用过程的框架,允许我们通过网络传输对象,但是传输的对象必须要实现Serializable
接口
2.地址缓存
有这么一种情况,我们所调用的服务都是正常的,但是服务中心(registry)挂掉了,这个时候我们还能不能正常访问服务呢?
是可以的。dubbo框架中,当服务都是正常运行的,但是注册中心(registry)挂掉了之后,依然允许我们正常的调用原有所使用的的服务
在consumer调用了某种服务后,dubbo框架会自动的将该服务的地址,协议等相关信息缓存到本地,虽然注册中心挂掉了,但是只要原有服务的地址没变,依然可以访问服务,这就是dubbo的地址缓存
3.超时机制
在生产环境中,我们通常会遇到这种情况,调用某种服务时,因为服务提供方的系统资源不够,导致服务执行耗时过长,导致整个程序过程就卡在了调用服务哪里
dubbo提供了一种超时机制,给服务设置一个超时限制,当服务调用超过了最大时限,系统就认为不需要再等待,通知服务调用方服务超时
超时是针对消费端还是服务端?
-
如果是针对消费端,那么当消费端发起一次请求后,如果在规定时间内未得到服务端的响应则直接返回超时异常,但服务端的代码依然在执行。
-
如果是针对服务端,那么当消费端发起一次请求后,一直等待服务端的响应,服务端在方法执行到指定时间后如果未执行完,此时返回一个超时异常给到消费端。
- 给服务提供者设置超时时间
// 超时针对服务端,那么当消费端发起一次请求后,一直等待服务端的响应,服务端在方法执行到指定时间后如果未执行完,此时返回一个超时异常给到消费端
// dubbo默认超时设置为1000毫秒
@DubboService(interfaceClass = DemoService.class,timeout = 3000)
public class DemoServiceImpl implements DemoService
,,,,,
- 给服务调用者设置超时时间
@RestController
public class DemoController
// 超时针对消费端,那么当消费端发起一次请求后,如果在规定时间内未得到服务端的响应则直接返回超时异常,但服务端的代码依然在执行
@DubboReference(timeout = 3000)
private DemoService demoService;
,,,,,
4.重试机制
在调用远程服务时,可能会因为网络问题,或者服务调用超时问题导致服务调用失败,dubbo框架提供了一种重试机制
当服务调用超时/调用失败之后,会重新尝试再次调用服务,如果调用服务的次数超过设置的最大重试次数后,就会认为服务调用失败
// 通过retries 来设置服务重试的最大次数
// 例如 当服务调用超时后,dubbo会再次调用服务,最多会重试三次
@DubboService(interfaceClass = DemoService.class,timeout = 3000,retries = 3)
public class DemoServiceImpl implements DemoService
,,,,,
5.多版本
当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。
在生产环境中,我们的软件需要经过多个版本的迭代更新,一般我们采用灰度更新的方式更新,即:先让一部分用户使用新版本服务,用户反馈没有问题,我们再面向全部用户推广
可以按照以下的步骤进行版本迁移:
- 在低压力时间段,先升级一半提供者为新版本
- 再将所有消费者升级为新版本
- 然后将剩下的一半提供者升级为新版本
服务端
// 通过version设置服务版本信息
// 一种服务可以有多个版本,一个服务可以有多个服务者提供
@DubboService(version = "1.0")
public class DemoServiceImpl implements DemoService
,,,,,
// 通过version设置服务版本信息
// 一种服务可以有多个版本,一个服务可以有多个服务者提供
@DubboService(version = "2.0")
public class DemoServiceImpl implements DemoService
,,,,,
消费端
@RestController
public class DemoController
// 通过version指定调用服务的哪个版本
@DubboReference(version = "1.0")
private DemoService demoService;
6.负载均衡
在生产环境中,我们通常是由集群的方式来提供服务的,此时就涉及到负载均衡的问题了
以怎么的方式来访问集群里面的机器,dubbo给我们提供一下几种策略
策略 | 作用 |
---|---|
random(默认策略) | 随机,按权重设置随机概率;在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重 |
roundrobin | 轮询,按公约后的权重设置轮询比率。存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上 |
leastactive | 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差;每个服务维护一个活跃数计数器。当A机器开始处理请求,该计数器加1,此时A还未处理完成。若处理完毕则计数器减1。而B机器接受到请求后很快处理完毕。那么A,B的活跃数分别是1,0。当又产生了一个新的请求,则选择B机器去执行(B活跃数最小),这样使慢的机器A收到少的请求。 |
consistenthash | 一致性 Hash,相同参数的请求总是发到同一提供者.当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动 |
在负载均衡中,是根据服务者权重(weight)来实行上述的策略,我们可以手动给服务设置策略与权重
所有的策略名称都在与之相对应的类里面
通过给服务来weight
设置服务的权重,通过设置loadbalance
来设置服务的负载均衡策略
// loadbalance既可以在服务端设定,也可以在消费方设置
@DubboService(weight = 100,loadbalance = "random")
public class DemoServiceImpl implements DemoService
......
@DubboReference(loadbalance = "random")
private DemoService demoService;
负载均衡只有在集群模式下才会生效
7.集群容错
在调用服务的时候,可能会出现调用服务失败的情况,在集群模式下,如何应对这种情况呢
dubbo为我们提供了一下几种集群容错的方案:
方案 | 作用 |
---|---|
Failover Cluster(默认方案) | 失败重试。当出现失败时,重试其他服务器,默认重试2次,使用retrires配置,一般用于读操作 |
Failfast Cluster | 快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录 |
Failsafe Cluster | 失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作 |
Failback Cluster | 失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作 |
Forking Cluster | 并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=“2” 来设置最大并行数 |
Broadcast Cluster | 广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。broadcast.fail.percent=20 代表了当 20% 的节点调用失败就抛出异常,不再调用其他节点 |
// 既可以针对消费方,也可以针对服务方
// 消费方
@DubboReference(cluster = "failover",retries = 2)
// 服务方
@DubboService(cluster = "failover")
具体的设置参数,可以参照官网API
8.服务降级
可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。
失败返回null值,但是不报错
@DubboReference(version = "1.0",mock = "fail:return null")
private DemoService demoService;
无论服务是否正常运行,直接不去访问,返回null
@DubboReference(version = "1.0",mock = "force:return null")
private DemoService demoService;
以上是关于dubbo的主要内容,如果未能解决你的问题,请参考以下文章