一、负载均衡
随机(默认)、轮询、最少活跃、一致性哈希
消费端和服务端都可以配置负载均衡策略。都配置以消费端为准
https://dubbo.apache.org/zh/docs/v2.7/user/examples/loadbalance/
最少活跃数
正常情况下,最少活跃数应该是在服务提供者端进行统计的,服务提供者统计有多少个请求正在执行中。
为不影响服务端性能,Dubbo是在消费端进行统计的。(只能统计当前消费者请求情况,不会统计全局)
- 每个消费者会缓存所调用服务的所有提供者,比如p1、p2、p3三个服务提供者,每个提供者内对应一个active属性,默认位0
- 消费者在发起调用时,消费者端会选择active最小的服务提供者,如果都相同,则随机。
- 选出某一个服务提供者后,假设p2,Dubbo就会对p2.active+1
- 然后真正发起调用。
- 消费端收到响应结果后,进行p2.active-1
这样就完成了对某个服务提供者当前活跃调用数进行了统计,并且并不影响服务调用的性能。
一致性哈希
默认根据第一个参数计算hash,决定调用服务,参数相同时,会调用同一台服务
二、服务超时
服务提供者和服务消费者,都可以配置服务超时时间。都配置以消费端为准。
消费者调用步骤
消费端调用服务时,消费端会收到超时异常(因为消费端超时了),服务端一切正常(服务端没有超时)
三、集群容错
Failover Cluster(失败自动切换)【默认重试2次】
Failfast Cluster(快速失败)
Failsafe Cluster(失败安全)
Forking Cluster(并行调用多个服务提供者,一个成功即可)
Broadcast Cluster(广播所有服务提供者,必须都成功才成功)
官方文档很清晰。https://dubbo.apache.org/zh/docs/v2.7/user/examples/fault-tolerent-strategy/
四、服务降级
当非关键服务调用出错时,不抛异常,返回预定数据。 具体操作,可以看官方文档例子:https://dubbo.apache.org/zh/docs/v2.7/user/examples/service-downgrade/
/**
* mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
* mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
*/
@DubboReference(mock = "force:return null")
//@DubboReference(mock = "fail:return null")
private MockService mockService;
服务降级与集群容错区别
- 集群容错,针对的是整个集群,是整个集群范围内的容错
服务降级,是单个服务提供者自身的容错。(不会抛出异常,也不会触发集群容错)
五、本地存根
本质是一段在消费者端执行的逻辑,逻辑可以由服务提供者提供(也可以在消费端实现)。
可以利用这种机制在消费者调用服务前(或后),做一些额外处理(类似装饰者模式,将原服务进行封装)
实现类必须实现对应服务的接口。可以作为服务降级的一种处理方式
官方文档例子:https://dubbo.apache.org/zh/docs/v2.7/user/examples/local-stub/ ```java @Component(“demoServiceComponent”) public class DemoServiceComponent implements DemoService {//默认查找接口所在包下的接口名+Stub的类:org.apache.dubbo.demo.DemoServiceStub //@DubboReference(stub = “true”) //指定实现类 @DubboReference(stub = “org.apache.dubbo.demo.consumer.comp.DemoServiceConsumerStub”) private DemoService demoService;
@Override public String sayHello(String name) {
return demoService.sayHello(name);
} }
```java
public class DemoServiceConsumerStub implements DemoService {
private DemoService demoService;
public DemoServiceConsumerStub(DemoService demoService) {
this.demoService = demoService;
}
@Override
public String sayHello(String name) {
System.out.println("调用前处理逻辑");
String sayHello = null;
try {
sayHello = demoService.sayHello(name);
System.out.println("执行逻辑返回:"+sayHello);
} catch (Exception e) {
System.out.println("调用远程服务失败了。");
}
System.out.println("调用后处理逻辑");
return sayHello;
}
}
调用前处理逻辑
执行逻辑返回:Hello world, response from provider: 192.168.1.4:20880
调用后处理逻辑
六、本地伪装
通常用于服务降级,比如某验权服务,当服务提供方全部挂掉后,客户端不抛出异常,而是通过 Mock 数据返回
授权失败。也可用于测试环境。
mock逻辑可以在消费端,也可以在提供端
官方示例:https://dubbo.apache.org/zh/docs/v2.7/user/examples/local-mock/
@Component("demoServiceComponent")
public class DemoServiceComponent implements DemoService {
/**
* mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
* mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
*/
//@DubboReference(mock = "force:return null")
//@DubboReference(mock = "fail:return null")
@DubboReference(mock = "force:org.apache.dubbo.demo.consumer.comp.MockServiceHandler")
private MockService mockService;
@Override
public List<Integer> callMock(Integer integer) {
List<Integer> call = mockService.call(integer);
System.out.println("调用降级服务返回值:" + call);
return call;
}
public class MockServiceHandler implements MockService {
@Override
public List<Integer> call(Integer integer) {
System.out.println("执行mock服务");
return Lists.newArrayList(991);
}
}
执行mock服务
调用降级服务返回值:[991]
七、参数回调
如果当前服务支持参数回调,即:对于服务接口中的某个方法,如果想支持消费者在调用这个方法时能设置回调逻辑,那么该方法就需要提供一个入参用来表示回调逻辑。
因为Dubbo协议是基于长连接的,所以消费端在两次调用同一个方法时想指定不同的回调逻辑,那么就需要在调用时在指定一定key进行区分。
个人认为,参数回调意义不大。如果想调用消费端,消费端提供对外接口即可
官方文档:https://dubbo.apache.org/zh/docs/v2.7/user/examples/callback-parameter/
@Component("demoServiceComponent")
public class DemoServiceComponent implements DemoService {
@DubboReference
private CallbackService callbackService;
@Override
public void callCallback(){
callbackService.addListener("1", new CallbackListenerImpl());
}
}
// 使用@Method指定用与回调的方法:addListener。
// 使用@Argument指定下标为1的参数用于回调。
// callbacks指定最大同时支持回调数
@DubboService(methods = {@Method(name = "addListener",arguments = {@Argument(index = 1,callback = true)})},callbacks = 10)
public class CallbackServiceImpl implements CallbackService {
@Override
public void addListener(String key, CallbackListener listener) {
System.out.println("提供者:回调测试");
listener.changed(getChanged(key)); // 发送变更通知
}
private String getChanged(String key) {
return "Changed: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
}
}
public class CallbackListenerImpl implements CallbackListener {
@Override
public void changed(String msg) {
System.out.println("消费者被服务端调用了"+msg);
}
}
提供者输出
提供者:回调测试
消费者输出
消费者被服务端调用了Changed: 2022-10-29 21:46:54
八、异步调用
官方文档:https://dubbo.apache.org/zh/docs/v2.7/user/examples/async-call/
九、泛化调用
服务提供者未提供接口依赖的情况下,可以调用提供者服务。但是需要知道提供者接口规范
官方文档:https://dubbo.apache.org/zh/docs/v2.7/user/examples/generic-reference/
@Component("demoServiceComponent")
public class DemoServiceComponent implements DemoService {
@DubboReference(id="demoService",interfaceName = "org.apache.dubbo.demo.DemoService",generic = true)
private GenericService genericService;
@Override
public void callGenericService(){
System.out.println("泛化调用");
Object invoke = genericService.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"泛化调用"});
System.out.println(invoke);
}
}
十、泛化服务
1.可以用于实现通用的mock服务;
2.对于消费者,在没有引入提供者接口情况下,可以进行调用服务。
3.对于提供者,可以不定义接口,实现服务暴露。
官方文档:https://dubbo.apache.org/zh/docs/v2.7/user/examples/generic-service/
/**
* 可以用于实现通用的mock服务
* @Author:masterlu
* @Date:2022/10/29 10:16 下午
*/
@DubboService(interfaceName = "org.apache.dubbo.demo.DemoService",version = "generic")
public class GenericServiceImpl implements GenericService {
@Override
public Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException {
if ("sayHello".equals(method)) {
return "Welcome " + args[0];
}
}
}
十一、Dubbo中的REST
REST也是Dubbo所支持的一种协议。
主要用于:没有使用Dubbo框架服务消费者,使用Dubbo服务提供的服务。
官方文档:https://dubbo.apache.org/zh/docs/v2.7/user/rest/
依赖注解坐标
<!--rest 注解支持-->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
<!--rest 协议支持-->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-rest</artifactId>
</dependency>