二Dubbo设计基础--3Mock机制和Stub机制
二Dubbo设计基础--3Mock机制和Stub机制
2.3.1 Mock机制
(https://maimai.cn/article/detail?fid=1414002536&efid=1ClnCEtvvjXp5j1knp2Trw)
-
Cluster是一个通用代理类,会根据URL中的cluster参数值定位到实际的Cluster实现类也就是FailoverCluster。这里用到了@SPI注解,也就是需要ExtensionLoader扩展点加载机制,而该机制在实例化对象时,会在实例化后自动套上Wapper;
-
但是是集群模式所以需要Dubbo中另外一个核心机制——Mock。Mock可以在测试中模拟服务调用的各种异常情况,还可以实现服务降级。在MockerClusterInvoker中,Dubbo先检查URL中是否存在mock参数。(这个参数可以通过服务治理后台Consumer端的屏蔽和容错进行设置或者直接动态设置mock参数值)如果存在force开头,这不发起远程调用直接执行降级逻辑。如果存在fail开头,则在远程调用异常时才会执行降级逻辑。
-
可以说注册中心为集群模式时,Invoker就会外面多包裹一层mock逻辑。是通过Wapper机制实现的。最终可以在调用或者重试时,每次都通过Dubbo内部的负载均衡机制选出多个Invoker中的一个进行调用;
本地伪装通常用于在远程调用出错的情况下服务降级,即本地伪装用来做容错处理
测试:通过将服务端设置睡眠,使得客户端调用超时,抛出异常。
public String sayHello(String name) {
// Dubbo 默认的超时时间是 1000 ms,这里通过睡眠 5000ms 来达到触发超时异常的发生
// 由于超时的发生,这个结果并不会被返回给客户端,取而代之的是 org.apache.dubbo.remoting.TimeoutException
try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }
return "Hello " + name;
}
在客户端提供本地伪装的实现。当远程调用发生错误的时候,返回给调用方的不是服务端的 "hello name",取而代之的是 "mock name"。
public class DemoServiceMock implements DemoService {
public String sayHello(String name) {
System.out.println("about to execute mock: " + DemoServiceMock.class.getSimpleName());
return "mock " + name;
}
}
要使用本地伪装的话,还需要在 mock-consumer.xml 中配置属性 mock。可以简单的通过指定 mock="true" 来告诉 Dubbo 框架使用本地伪装,这个时候,本地伪装的包名需要和服务接口的包名一致,类名必须在服务接口的类名后加上 Mock 的后缀。例如,当服务接口名是 com.alibaba.dubbo.demo.DemoService 时,本地存根的全类名应该是 com.alibaba.dubbo.demo.DemoServiceMock。
<dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.demo.DemoService" mock="true">
<dubbo:method name="sayHello" retries="0"></dubbo:method>
</dubbo:reference>
如果不希望使用默认的命名规则,也可以直接通过 mock 属性来指定本地伪装的全类名
<dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.demo.DemoService"
mock="com.alibaba.dubbo.demo.consumer.DemoServiceMock">
<dubbo:method name="sayHello" retries="0"></dubbo:method>
</dubbo:reference>
通过提供一个本地伪装的类,可以最大限度的控制出错之后的容错逻辑。有的时候,业务上并不需要这样灵活的机制,只有返回一个默认值的诉求,这个时候提供一个完整的本地伪装的实现就显得有点重了。或者线上出错的时候,应用并没有打包本地伪装,需要通过推送规则的方式临时对服务降级。Dubbo 框架为上面的这两种诉求都提供了快捷方式,帮助用户快速配置服务降级。
总结
本文介绍了 Dubbo 中本地存根和本地伪装的概念和用法。从本质来讲,本地存根和本地伪装等同于面向切面编程中的概念,通过诸如 Spring 框架提供的 AOP 编程可以达到同样的目的。通过本文如何开发一个本地存根和本地伪装的示例,读者可以直观的感受到通过框架提供的机制更加方便快捷。同时,对于很多简单的场景和动态配置推送的场景,框架提供了仅通过配置而无需编码的方式来满足,进一步提升了框架使用者的效率。
2.3.2 Stub机制
(https://www.cnblogs.com/caoxb/p/13140390.html)—-copy
本地存根的工作方式与 AOP 的 around advice 类似,而本地伪装的工作方式等同于 AOP 中的 after-throwing advice,也就是说,只有当远程调用发生 exception 的时候才会执行本地伪装。本地存根和本地伪装的工作流程如下图所示:

- 服务消费者发起调用
- 如果服务消费者端存在本地存根 Stub 的话,会先执行本地存根
- 本地存根 Stub 持有远程服务的 Proxy 对象,Stub 在执行的时候,会先执行自己的逻辑 (before),然后通过 Proxy 发起远程调用,最后在返回过程之前也会执行自己的逻辑 (after-returning)
- 如果远程服务的 Proxy 对象在执行过程中抛出了 exception,会执行服务消费端的本地伪装 Mock 的逻辑 (after-throwing),返回容错数据,从而达到服务降级的目的
一、本地存根 Stub
public class DemoServiceStub implements DemoService { // #1
private final DemoService demoService;
public DemoServiceStub(DemoService demoService) { // #2
this.demoService = demoService;
}
@Override
public String sayHello(String name) { // #3
System.out.println("before execute remote service, parameter: " + name); // #4
try {
String result = demoService.sayHello(name); // #5
System.out.println("after execute remote service, result: " + result); // #6
return result;
} catch (Exception e) {
System.out.println("fail to execute service"); // #7
return null;
}
}
}
DemoServiceStub 运行在客户端,要使用本地存根的话,还需要在 .xml 中配置属性 stub。可以简单的通过指定 stub="true" 来告诉 Dubbo 框架使用本地存根,这个时候,本地存根的包名需要和服务接口的包名一致,类名必须在服务接口的类名后加上 Stub 的后缀。例如,当服务接口名是 com.alibaba.dubbo.demo.DemoService 时,本地存根的全类名应该是com.alibaba.dubbo.demo.DemoServiceStub。
<dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.demo.DemoService" stub="true">
<dubbo:method name="sayHello" retries="0"></dubbo:method>
</dubbo:reference>
如果不希望使用默认的命名规则,也可以直接通过 mock 属性来指定本地伪装的全类名
<dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.demo.DemoService"
stub="com.alibaba.dubbo.demo.consumer.DemoServiceStub">
<dubbo:method name="sayHello" retries="0"></dubbo:method>
</dubbo:reference>
通过提供一个本地伪装的类,可以最大限度的控制出错之后的容逻辑。有的时候,业务上并不需要这样灵活的机制,只有返回一个默认值的诉求,这个时候提供一个完整的本地伪装的实现就显得有点重了。或者线上出错的时候,应用并没有打包本地伪装,需要通过推送规则的方式临时对服务降级。Dubbo 框架为上面的这两种诉求都提供了快捷方式,帮助用户快速配置服务降级。

浙公网安备 33010602011771号