对DUBBO本地存根和本地伪装一点总结和思考

it2022-07-03  112

参考文章:http://dubbo.apache.org/zh-cn/blog/dubbo-stub-mock.html

 

什么是本地存根和本地伪装

本地存根和本地伪装就是在消费方部署一个实现了目标接口的伪服务。用于在调用真正服务之前,之后的处理工作。其职能有点类似于Spring 的AOP。

stub和mock工作流程图

 

为什么要使用本地存根和本地伪装

本地存根

通常情况下,我们调用接口之前都会生成一个请求对象。并且对请求对象中的必传字段以及类型做一定的校验,如果不满足调用接口条件,可能需要抛出异常或者其他处理方式。所以本地存根的作用可以认为是预处理信息。

本地伪装

如果请求条件达到了调用接口的要求,但是调用失败了。这个时候又如何处理?可以通过本地伪装的方式,mock一个对象返回。可以认为是服务消费方自己做的一个容错处理机制类。

通过上边两点,我们可以清楚的知道stub service和mock service发挥的作用类似于spring aop。所以,本着约定大于配置的要求。优先选择stub和mock而非spring sop。

 

如何使用本地存根和本地伪装

本段内容完全拷贝自官方文档。因为教程也很完善~

使用本地存根的条件限制:

首先本地存根 Stub 是服务接口的一个实现本地存根的实现需要提供一个拷贝构造方法,方便框架将远程调用的 Proxy 对象注入进来同样的,本地存根需要提供服务接口中所有方法的实现。在本例中,需要实现 sayHello 方法在真正发起远程调用之前,用户可以在本地执行一些操作。在本例中,在日志中记录传入的参数通过框架传入的 Proxy 对象真正发起远程调用在远程调用结束后,也可以加入本地代码的执行。在本例中,在日志中记录远程调用的返回结果如果发生错误的时候,也可以做一些错误恢复的动作。在本例中,在日志中记录异常。当然,如果提供了本地伪装的话,catch 中的逻辑是可以省略掉的 public class DemoServiceStub implements DemoService { // #1 private static Logger logger = LoggerFactory.getLogger(DemoServiceStub.class); private final DemoService demoService; public DemoServiceStub(DemoService demoService) { // #2 this.demoService = demoService; } @Override public String sayHello(String name) { // #3 logger.info("before execute remote service, parameter: " + name); // #4 try { String result = demoService.sayHello(name); // #5 logger.info("after execute remote service, result: " + result); // #6 return result; } catch (Exception e) { logger.warn("fail to execute service", e); // #7 return null; } } }

 stub-consumer.xml 中配置属性 stub

指定 stub="true" 来告诉 Dubbo 框架使用本地存根,这个时候,本地存根的包名需要和服务接口的包名一致,类名必须在服务接口的类名后加上 Stub 的后缀。例如,当服务接口名是 org.apache.dubbo.samples.stub.api.DemoService 时,本地存根的全类名应该是 org.apache.dubbo.samples.stub.api.DemoServiceStub。

<dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.samples.stub.api.DemoService" stub="true"/>

如果不希望使用默认的命名规则,也可以直接通过 stub 属性来指定本地存根的全类名。

<dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.samples.stub.api.DemoService" stub="org.apache.dubbo.samples.stub.impl.DemoStub"/>

 

要使用本地伪装的话,还需要在 mock-consumer.xml 中配置属性 mock。可以简单的通过指定 mock="true" 来告诉 Dubbo 框架使用本地伪装,这个时候,本地伪装的包名需要和服务接口的包名一致,类名必须在服务接口的类名后加上 Mock 的后缀。例如,当服务接口名是 org.apache.dubbo.samples.stub.api.DemoService 时,本地存根的全类名应该是 org.apache.dubbo.samples.stub.api.DemoServiceMock。

public class DemoServiceMock implements DemoService { private static Logger logger = LoggerFactory.getLogger(DemoServiceMock.class); public String sayHello(String name) { logger.warn("about to execute mock: " + DemoServiceMock.class.getSimpleName()); return "mock " + name; } }

  mock-consumer.xml 中配置属性 mock

<dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.samples.mock.api.DemoService" mock="true"/> <dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.samples.mock.api.DemoService" mock="org.apache.dubbo.samples.mock.impl.DemoMock"/>

 

能不能不用本地存根和本地伪装

对于分散的参数校验和分散的结果处理逻辑,对于业务代码而言兼职是噩梦。为什么这么说呢,谁都无法避免定位线上问题,那么需要看代码查找问题的时候,这种分散参数校验和结果处理逻辑会很头疼。所以,在熟悉调用接口的契约时,可以将这些逻辑放在一起。所以,可以不用这种处理方式。

如何解决服务消费和服务调用之间容错和有好关系呢?

设置完善的响应码规则。消费方通过响应码规则去处理响应的逻辑。为了增强容错能力,响应响应吗规则应该是配置文件。热加载在JVM内存中。


最新回复(0)