基本使用介绍
- 服务提供方基于接口编写实现类
- 配合Spring配置保留Dubbo服务接口(包括:注册中心地址,协议名及端口)
- 消费者配合Spring,引用dubbo服务接口(包括:配置注册中心地址)
- 启动spring容器,获取bean,调用方法
- 详见官网示例
- 需要注意的是Dubbo中对与服务的定义:
- 接口可以叫服务,接口实现也可叫服务
- 某个服务地址也可叫服务
- 一个完整的服务ID定义包括 协议、IP、端口、接口名、分组、版本
- 比如:
dubbo://192.168.2.12:8080/user/getUserInfo:user_group:1.0.1
负载均衡
- 消费端与服务端均可配置,同时配置以消费端为准
- 支持算法
- Random(默认)
- RoundRobin
- LeastActive(最少活跃调用次数)
- ConsistentHash(相同参数的请求总发给统一提供者)
- 自定义扩展
- 思考:最少活跃次数是如何统计的?
- 每个消费者自己记录被调用服务端active属性
- 选定服务调用前+1,收到结果后-1
- 优先选active为最小,相同则随机
服务超时
- 服务端和消费端都支持配置,但效果不一样
- 消费端配的,表示调用服务端的超时时间,超过超时时间则抛出异常
- 服务端若超出自己配置的超时时间,则只会打印一个警官日志
集群容错
- 若存在多个实例,消费者调用服务提供者报错时处理机制
- Failover:重试其他实例,默认重试2次,可配,默认
- Failfast:快速失败,调用报错即立即报错,通常用于非幂等性操作场景
- Failsafe:安全失败,异常视直接忽略,用于比如记录日志场景
- Failback:失败自动恢复,使用日志记录,后面定时重发,通常用于发消息场景
- Forking:并行调用多个实例,只要一个以上成功即正常返回,也可配置,用于实时性要求较高的读操作,但浪费资源
- Broadcast:广播调用,逐个调用,任意一台报错则报错;比如通知所有实例更新本地缓存等本地资源信息等操作,也可配置失败比例限制;
服务降级
- 消费者调用提供者,若报错了采取的措施;
- 降级与集群容错的区别:集群是集群范围内,降级是指单个服务提供者内;
- 可通过降级屏蔽某个非关键功能,定义降级后的返回策略
- 该机制说白了就是mock思想,相当于挡板
- 用法1:
mock=force:return+null
,不管是否异常直接返回null值 - 用法2:
mock=fail:return+null
,方法调用在失败后,再返回null
本地存根
- 名字很抽象,就是Stub机制
- 说白了,消费者本地包装一下调用提供者逻辑
- 可在调用之前、之后做一些操作,如参数校验,结果缓存等
- 也可以利用该机制做服务调用容错
package com.foo;
public class BarServiceStub implements BarService {
private final BarService barService;
// 构造函数传入真正的远程代理对象
public BarServiceStub(BarService barService){
this.barService = barService;
}
public String sayHello(String name) {
// 此代码在客户端执行, 你可以在客户端做ThreadLocal本地缓存,或预先验证参数是否合法,等等
try {
return barService.sayHello(name);
} catch (Exception e) {
// 你可以容错,可以做任何AOP的事项
return "容错数据";
}
}
}
本地伪装
- 就是上面提到的服务降级
- 详见官网:本地伪装
参数回调
- 消费者调用服务提供者后,支持服务提供者回调消费者某个回调逻辑
- Dubbo协议是基于长连接的,故若在两次调用同样的服务提供者方法,则需要用key加以区分
- 此功能相当于可监听服务提供者那边的处理情况
异步调用
- 直接把它理解为Future
- 基于 NIO 的非阻塞实现并行调用
- 客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小
泛化调用
- 用于客户端没有 API 接口及模型类元的情况
- 通常用于框架集成
- 例如实现一个通用的服务测试框架,可通过 GenericService调用所有服务实现
import org.apache.dubbo.rpc.service.GenericService;
...
// 引用远程服务
// 该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
// 弱类型接口名
reference.setInterface("com.xxx.XxxService");
reference.setVersion("1.0.0");
// 声明为泛化接口
reference.setGeneric(true);
// 用org.apache.dubbo.rpc.service.GenericService可以替代所有接口引用
GenericService genericService = reference.get();
// 基本类型以及Date,List,Map等不需要转换,直接调用
Object result = genericService.$invoke("sayHello", new String[] {"java.lang.String"}, new Object[] {"world"});
// 用Map表示POJO参数,如果返回值为POJO也将自动转成Map
Map<String, Object> person = new HashMap<String, Object>();
person.put("name", "xxx");
person.put("password", "yyy");
// 如果返回POJO将自动转成Map
Object result = genericService.$invoke("findPerson", new String[]
{"com.xxx.Person"}, new Object[]{person});
...
泛化服务
- 实现了GenericService接口的就是泛化服务
- 实现 GenericService 接口处理所有服务请求
- 主要用于服务器端没有API接口及模型类元的情况
package com.foo;
public class MyGenericService implements GenericService {
public Object $invoke(String methodName, String[] parameterTypes, Object[] args) throws GenericException {
if ("sayHello".equals(methodName)) {
return "Welcome " + args[0];
}
}
}
REST
- 新版本Dubbo所支持的一种协议
- 比如消费者没有使用Dubbo也想调用Dubbo服务
- 如果某个服务只有REST协议可用,那么该服务必须用@Path注解定义访问路径
- 可以实现服务的”一次编写,到处访问“
管理台
- dubbo-admin,下载源码打包启动接口用,springboot工程
- dubbo支持配置zk、redis等为配置中心
- 进管理台可修改zk或其他配置中心内容
- 总体提供的功能还在不断完善
- 特殊功能关注:动态配置功能,可动态修改服务各项参数
- 条件路由配置
- 针对消费者与提供者
- 可用表示配置路由规则
- 可配置黑名单策略
- 可用于实现隔离不同机房等功能
- 标签路由
- 可用于蓝绿发布或灰度发布
- 可给应用实例打标签
- 消费者带标签访问时,可根据标签找到对应的提供者