stub:
远程服务后,客户端通常只剩下接口,而实现全在服务器端,但提供方有些时候想在客户端也执行部分逻辑,那么就在服务消费者这一端提供了一个Stub类,然后当消费者调用provider方提供的dubbo服务时,客户端生成 Proxy 实例,这个Proxy实例就是我们正常调用dubbo远程服务要生成的代理实例,然后消费者这方会把 Proxy 通过构造函数传给 消费者方的Stub ,然后把 Stub 暴露给用户,Stub 可以决定要不要去调 Proxy。会通过代理类去完成这个调用,这样在Stub类中,就可以做一些额外的事,来对服务的调用过程进行优化或者容错的处理。附图:
mock:
RPC在服务异常时,请求返回mock的(假)数据,而不是简单的抛出异常,达到服务降级和本地mock的效果.只有在服务抛出异常时才会调用。
stub会做一些日志或者其他校验判断是否进行服务的调用而mock主要用于服务降级的作用
服务接口:
public interface DemoService {
String sayHello(String name);
}
服务端实现
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
}
}
服务端配置:
<!-- provider's application name, used for tracing dependency relationship -->
<dubbo:application name="demo-provider"/>
<!-- use multicast registry center to export service -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>
<!-- use dubbo protocol to export service on port 20880 -->
<dubbo:protocol name="dubbo" port="20881"/>
<!-- service implementation, as same as regular local bean -->
<bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
<!-- declare the service interface to be exported -->
<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
consumer的实现
public class Consumer {
public static void main(String[] args) {
//Prevent to get IPV6 address,this way only work in debug mode
//But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not
System.setProperty("java.net.preferIPv4Stack", "true");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
context.start();
DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy
int count = 0;
while (true) {
try {
Thread.sleep(1000);
String hello = demoService.sayHello("world"+ count++); // call remote method
System.out.println(hello); // get result
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
}
stub的实现:
public class DemoServiceStub implements DemoService {
private final DemoService demoService;
public DemoServiceStub(DemoService demoService) { // #2
this.demoService = demoService;
}
@Override
public String sayHello(String name) {
if(name.contains("2")){
return "异常信息";
}else{
return demoService.sayHello(name);
}
}
}
mock的实现:
public class DemoServiceMock implements DemoService {
@Override
public String sayHello(String name) {
return "server fail mock " + name;
}
}
配置信息:
<dubbo:application name="demo-consumer"/>
<!-- use multicast registry center to discover service -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>
<!-- generate proxy for the remote service, then demoService can be used in the same way as the
local regular interface -->
<dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.demo.DemoService" mock="com.alibaba.dubbo.demo.consumer.DemoServiceMock" stub="com.alibaba.dubbo.demo.consumer.DemoServiceStub"/>
服务调用的整体结果:
当我们停止provider会触发mock
手贱的我,把mock去掉,发现stub功能上完全和mock差不多,what。。。。。这是什么个情况。。
探寻真理的路上,我果断的选择了debug,发现这个demoservice是DemoServiceStub,这样我们就可以猜测出这很明显是proxy的老套路了,那proxy又是在那实现的呢?????
通过代理工厂创建了代理对象stub,所以消费者中的注入的demoservice本身就是stub实体
我们继续看一下mock的实现,调用服务失败之后的逻辑
所以本质上本地存根和mock的实现方法是不一样的,虽然能达到相同的结果
回复 8888可以领取面试资料