Check启动检查

根据之前的学习,我们简单理解的Dubbo远程调用的基本流程,服务提供者注册到注册中心,然后服务消费者通过监听注册中心达到远程调用的目的,那么如果注册中心中没有消费者对应的接口会怎么样呢?

开启Zookeeper,在不运行服务提供者的情况下直接运行消费者,结果是:

// 抛出了异常信息
java.lang.reflect.InvocationTargetException: null
// 其中可以看到有价值的异常信息为:
Failed to check the status of the service site.hanzhe.service.UserService. No provider available for the service site.hanzhe.service.UserService from the url zookeeper://127.0.0.1:2181/com.alibaba.dubbo ......

大致含义为我们通过@Reference注解进行远程调用,但是注册中心中并没有对应的服务所以报错

这样依赖我们就知道了远程调用是在程序初始化的时候就已经与远程服务建立连接了,现在我们不希望它初始化时连接,我们希望在真正用到它的时候再进行连接,这样我们提供者就可以随时注册上去提供服务,想要实现这个功能可以利用注解中的check属性:

@RestController
public class UserController {
@Reference(check = false)
private UserService userService; @GetMapping("/selectUser")
public List<UserEntity> selectUse() {
return userService.selectList();
}
}

check属性为启动检查,默认值为true,当我们设置为false之后启动就不报错了,然后随时启动提供者进行远程调用

通过设置@Referencecheck属性可以关闭启动检查,但是如果我们程序中存在着大量的远程接口就不方便操作了,这里Dubbo为我们提供了一个全局的消费者配置:

# 通过设置dubbo.consumer.check属性来设置消费者所有远程接口的启动检查
dubbo:
consumer:
check: false

这时候我们在移除@Referencecheck属性,也可以实现相同的功能,且一劳永逸!

Timeout超时时间

Dubbo是一款RPC远程调用框架,远程调用肯定离不开网络,那么如果在远程调用的时候时间过长应该怎么处理?

做一个测试,在服务提供者中返回结果之前做一个阻塞效果:

@Service
@com.alibaba.dubbo.config.annotation.Service
public class UserServiceImpl implements UserService { @Override
public List<UserEntity> selectList() {
UserEntity entity1 = new UserEntity("马保国", "69", "男");
UserEntity entity2 = new UserEntity("张全蛋", "31", "男");
try {
// 这里让该线程睡2秒钟
Thread.sleep(2000);
} catch (InterruptedException e) { }
return Arrays.asList(entity1, entity2);
} }

然后在消费者进行远程调用测试,抛出了如下异常:

com.alibaba.dubbo.remoting.TimeoutException: Waiting server-side response timeout by scan timer ...

简单来说就是服务端响应太慢请求超时了,通过查看官网可知道默认的超时时间为1000ms,也就是说当请求超过1秒就会被抛弃,但是有些时候1秒有些太短,这里在消费者方通过@Referencetimeout属性手动设置超时时间:

@RestController
public class UserController {
@Reference(check = false, timeout = 3000)
private UserService userService; @GetMapping("/selectUser")
public List<UserEntity> selectUse() {
return userService.selectList();
}
}

在远程调用时设置超时时间为三秒,这样一来就可以调用成功了!和检查属性一样,超时时间也可以全局设置:

# 通过设置dubbo.consumer.check属性来设置消费者所有远程接口的启动检查
dubbo:
consumer:
check: false
timeout: 3000

Retries请求重发

我们可以通过延长请求超时时间来提高稳定率,但如果出现了意外情况在规定的时间内也没能完成操作,那么我们就需要进行重发进行操作了:

@RestController
public class UserController {
// retries当请求失败后,重新发送该请求,设置重发次数最多为2次
// 加上本身的一次也就是一共3次请求,如果3次都失败那就是真正的失败
@Reference(check = false, retries=2)
private UserService userService; @GetMapping("/selectUser")
public List<UserEntity> selectUse() {
return userService.selectList();
}
}

我们在服务提供者中使用打印语句来观察请求的次数,可以看到的确调用了三次:

关于请求重发

并不是所有请求都可以进行请求重发的,原则上只有幂等可以设置重发,非幂等不可以设置重发

  • 幂等:类似delete、update、select操作多次执行并不会对数据造成影响
  • 非幂等:类似inert操作多次执行可能会造成不可控的后果

当然这只是原则,实际上还需要根据业务逻辑来判断是否可以使用,例如UPDATE user SET number = number + #{number} .. 就不适合重发

Version多版本

服务提供者通过实现接口,暴露出接口的实现类,从而在消费者端实现远程调用,在服务者暴露接口时可以针对某一个接口暴露多个实现类,每个实现类有着自己的版本号,通过版本号来控制调用哪个实现

@Service
// 设置当前service实现版本为v1
@com.alibaba.dubbo.config.annotation.Service(version="v1")
public class UserServiceImpl implements UserService { @Override
public List<UserEntity> selectList() {
UserEntity entity1 = new UserEntity("马保国", "69", "男");
UserEntity entity2 = new UserEntity("张全蛋", "31", "男");
return Arrays.asList(entity1, entity2);
} } @Service
// 复制一个实现,修改版本为v2,并修改数据内容
@com.alibaba.dubbo.config.annotation.Service(version="v1")
public class UserServiceImpl implements UserService { @Override
public List<UserEntity> selectList() {
UserEntity entity1 = new UserEntity("马保国", "69", "女");
UserEntity entity2 = new UserEntity("张全蛋", "31", "女");
return Arrays.asList(entity1, entity2);
} }

然后在消费者端通过修改Reference注解的version属性来控制调用:

@RestController
public class UserController {
@Reference(check = false, retries=2, version = "v1")
private UserService userService; @GetMapping("/selectUser")
public List<UserEntity> selectUse() {
return userService.selectList();
}
}

启动当前消费者,然后将v1修改为v2,修改端口号来启动第二个消费者,分别调用两个接口,结果为:

Stub本地存根

本地存根,指的是除开远程调用的实现之外,自己本地也有实现,且可以根据参数来决定是否使用本地实现

在消费者端创建一个接口的实现类:

// 这个实现类就是本地存根类
public class UserServiceImpl implements UserService {
// 这里用来存放远程调用的service对象
private final UserService userService;
// 远程对象通过构造方法传入
public UserServiceImpl(UserService userService) {
this.userService = userService;
}
// 复写方法中根据各种情况来判断是否使用远程实例
@Override
public List<UserEntity> selectList() {
try {
return userService.selectList();
} catch (Exception e) {
System.err.println("远程调用出现异常!");
return null;
}
} }

然后在controller位置的@Reference注解使用stub属性,属性值为本地存根的类的全路径名:

@RestController
public class UserController { @Reference(check = false, stub = "site.hanzhe.service.impl.UserServiceImpl")
private UserService userService; @GetMapping("/selectUser")
public List<UserEntity> selectUse() {
return userService.selectList();
} }

可以在服务提供者的位置模拟异常来查看是否设置成功

Dubbo学习笔记(二) Dubbo的基本配置的更多相关文章

  1. dubbo学习笔记(二)dubbo中的filter

    转:https://www.cnblogs.com/cdfive2018/p/10219730.html dubbo框架提供了filter机制的扩展点(本文基于dubbo2.6.0版本). 扩展接口 ...

  2. dubbo学习笔记二(服务调用)

    项目结构 代码示例 由于之前的IEchoService 的一个方法只是在服务端控制台打印,不便在浏览器测试,所以新添加的方法 api和服务端代码变更 public interface IEchoSer ...

  3. Hibernate学习笔记二:常用映射配置

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6760895.html 一:单向一对一 常用唯一外键的方法来配置单向一对一关系. 1:实体关系 类A中有类B对象 ...

  4. JMX学习笔记(二)-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...

  5. InterSystems Ensemble学习笔记(二) Ensemble创建镜像, 实现自动故障转移

    系列目录 InterSystems Ensemble学习笔记(一) Ensemble介绍及安装InterSystems Ensemble学习笔记(二) Ensemble创建镜像, 实现自动故障转移 一 ...

  6. kvm虚拟化学习笔记(二)之linux kvm虚拟机安装

    KVM虚拟化学习笔记系列文章列表----------------------------------------kvm虚拟化学习笔记(一)之kvm虚拟化环境安装http://koumm.blog.51 ...

  7. amazeui学习笔记二(进阶开发5)--Web 组件开发规范Rules

    amazeui学习笔记二(进阶开发5)--Web 组件开发规范Rules 一.总结 1.见名知意:见那些class名字知意,见函数名知意,见文件名知意 例如(HISTORY.md Web 组件更新历史 ...

  8. JDBC学习笔记二

    JDBC学习笔记二 4.execute()方法执行SQL语句 execute几乎可以执行任何SQL语句,当execute执行过SQL语句之后会返回一个布尔类型的值,代表是否返回了ResultSet对象 ...

  9. ZooKeeper学习笔记二:API基本使用

    Grey ZooKeeper学习笔记二:API基本使用 准备工作 搭建一个zk集群,参考ZooKeeper学习笔记一:集群搭建. 确保项目可以访问集群的每个节点 新建一个基于jdk1.8的maven项 ...

随机推荐

  1. (三)MySQL锁机制 + 事务

    转: (三)MySQL锁机制 + 事务 表锁(偏读) 偏向MyISAM存储引擎.开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率最高,并发最低. 查看当前数据库中表的上锁情况,0表示未上锁. sh ...

  2. Hi3559AV100外接UVC/MJPEG相机实时采图设计(二):V4L2接口的实现(以YUV422为例)

    下面将给出Hi3559AV100外接UVC/MJPEG相机实时采图设计的整体流程,主要实现是通过V4L2接口将UVC/MJPEG相机采集的数据送入至MPP平台,经过VDEC.VPSS.VO最后通过HD ...

  3. 007-变量的作用域和LED点阵

    变量 一.局部变量和全局变量 局部变量:函数内申明的变量,只在函数内有效. 全局变量:函数外部申明的变量.一个源程序文件有一个或者多个函数,全局变量对他们都起作用. 备注:全局变量有副作用,降低了函数 ...

  4. HDR(高动态范围)

    一: 简介 一般来说,当存储在帧缓冲(Framebuffer)中时,亮度和颜色的值是默认被限制在0.0到1.0之间的. 但是如果我们遇上了一个特定的区域,其中有多个亮光源使这些数值总和超过了1.0,又 ...

  5. iot漏洞入门

    路由器漏洞入门 下载项目https://github.com/praetorian-inc/DVRF 安装quem sudo apt install qemu-user-static 安装gdb-mu ...

  6. 2020年12月-第02阶段-前端基础-Day06

    CSS Day06 定位(position) 理解 能说出为什么要用定位 能说出定位的4种分类 能说出四种定位的各自特点 能说出我们为什么常用子绝父相布局 应用 能写出淘宝轮播图布局 1. CSS 布 ...

  7. 上线 Python 应用仅需一条命令的开源框架:Zappa(详细教程)

    本文面向有 Python Web 基础的小伙伴 作者:HelloGitHub-吱吱 这里是 HelloGitHub 推出的<讲解开源项目>系列,今天要向小伙伴们介绍一个 Python 无服 ...

  8. 线上MySQL读写分离,出现写完读不到问题如何解决

    大家好,我是历小冰. 今天我们来详细了解一下主从同步延迟时读写分离发生写后读不到的问题,依次讲解问题出现的原因,解决策略以及 Sharding-jdbc.MyCat 和 MaxScale 等开源数据库 ...

  9. IDEA修改jar包中class文件后重新生成jar包

    一.背景 最新想要修改rebeyond大佬的冰蝎项目,特地去网上搜索如何修改jar包中的源码再替换回去的方法,但由于现在的一些文章写的太烂,导致走了很多弯路,因此写下这篇快速使用IDEA修改源码并替换 ...

  10. 60秒定位问题,十倍程序员的Debug日常

    作者:陶建辉 这是我在 2020 年 5 月写的一篇内部博客,当时是希望研发和技术支持同学能够帮助用户快速定位 Bug,解决问题.2020 年 12 月我又迭代了一版,并还针对此进行了内部的培训.这段 ...