zoukankan      html  css  js  c++  java
  • Dubbo学习笔记-RPC扩展和本地Mock

    1.Dubbo介绍

    Dubbo,一个是一款高性能Java RPC框架.私以为有中文官方文档,就不再重复介绍了

    2.RPC扩展-本地存根stub

    RPC扩展功能:提前效验参数,缓存调用结果,日志记录等等,可以使用AOP织入这些扩展功能,但Dubbo提供了更灵活简单的实现-本地存根stub。
    

    3.本地Mock-本地伪装mock

    RPC在服务异常时,请求返回mock的(假)数据,而不是简单的抛出异常,达到服务降级和本地mock的效果.只有在服务抛出异常时才会调用。
    

    4.调用流程

    1. 服务消费者发起调用
    2. 如果服务消费者端存在本地存根 Stub 的话,会先执行本地存根
    3. 本地存根 Stub 持有远程服务的 Proxy 对象,Stub 在执行的时候,会先执行自己的逻辑 (before),然后通过 Proxy 发起远程调用,最后在返回过程之前也会执行自己的逻辑 (after-returning)
    4. 如果远程服务的 Proxy 对象在执行过程中抛出了 exception,会执行服务消费端的本地伪装 Mock 的逻辑 (after-throwing),返回容错数据,从而达到服务降级的目的

    5.本地存根实例

    定义一个demo接口

    public interface DemoService {
        String sayHello(String name);
    }
    

    根据约定大于配置原则,实现一个demo的stub实例

    // 类名约定为 继承接口+Stub
    public class DemoServiceStub implements DemoService { 
        private static Logger logger = LoggerFactory.getLogger(DemoServiceStub.class);
    
        private final DemoService demoService;
    
        // 本地存根的实现需要提供一个拷贝构造方法,方便框架将远程调用的 Proxy 对象注入进来
        public DemoServiceStub(DemoService demoService) {
            this.demoService = demoService;
        }
    
        // 本地存根需要提供服务接口中所有方法的实现。在本例中,需要实现 sayHello 方法
        @Override
        public String sayHello(String name) {
            // 进行预处理部分
            logger.info("before 执行远程服务, 入参: " + name); 
            try {
                // 执行原函数功能,重要!!!
                String result = demoService.sayHello(name);
                // 执行函数后续部分,这里也可以完成缓存的操作
                logger.info("after 执行远程服务, 出参: " + result);
                return result;
            } catch (Exception e) {
                // 异常处理部分
                logger.warn("执行失败! ", e);
                return null;
            }
        }
    }
    

    在prvider.xml中将服务暴露出去

    # resourcesspringmock-consumer.xml
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
           xmlns="http://www.springframework.org/schema/beans"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
        <!-- 提供方应用信息,用于计算依赖关系 -->
        <dubbo:application name="mock-demo-consumer"/>
        <dubbo:registry address="zookeeper://101.201.232.80:2181"/>
        <dubbo:metadata-report address="zookeeper://101.201.232.80:2181" />
    
        <!-- 用dubbo协议在本地20880端口通讯 -->
        <dubbo:protocol name="dubbo" port="20880"/>
    
        <!-- 和本地bean一样实现服务 -->
        <bean id="demoService" class="mock.impl.DemoServiceImpl"/>
    
        <!-- 暴露接口类名遵循约定 -->
        <dubbo:reference id="demoService" check="false" interface="mock.api.DemoService" stub="true"/>
        <!-- 类名不遵循约定,则指定全类名 -->
        <!-- <dubbo:reference id="demoService" check="false" interface="mock.api.DemoService" stub="mock.api.DemoServiceStub"/> -->
    
    </beans>
    

    6.本地伪装实例

    dubbo默认为1000ms会抛超时异常,我们就让线程sleep 5000ms来人为触发
    改造demo实现类如下,取消try则返回 hello + name,否则触发mock,返回 mock + name

    public class DemoServiceImpl implements DemoService {
    
        @Override
        public String sayHello(String name) {
            try {
                // 默认为1s无响应则抛超时异常,此处睡眠5s,使其抛出异常
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello " + name;
        }
    }
    

    根据约定大于配置原则,实现一个demo的mock实例

    // 类名:demo接口+Mock
    public class DemoServiceMock implements DemoService {
        // 原服务抛出异常,则执行对应函数
        @Override
        public String sayHello(String name) {
            return "mock " + name;
        }
    }
    

    消费者xml需要稍微改造

    # resourcesspringmock-consumer.xml
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
           xmlns="http://www.springframework.org/schema/beans"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
        <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
        <dubbo:application name="mock-demo-consumer"/>
    
        <!--使用multicast广播注册中心暴露发现服务地址 30s耗时-->
        <dubbo:registry timeout="30000" address="zookeeper://127.0.0.1:2181"/>
    
        <!-- 生成远程服务代理,可以和本地bean一样使用demoService 注意mock=true-->
        <dubbo:reference id="demoService" check="false" interface="mock.api.DemoService"
                         mock="true"/>
    
    </beans>
    

    7.参考

    1. 本地存根Stub:https://github.com/apache/dubbo-samples/tree/master/java/dubbo-samples-stub
    2. 本地伪装Mock:https://github.com/apache/dubbo-samples/tree/master/java/dubbo-samples-mock
    3. beiwei30:http://dubbo.apache.org/zh-cn/blog/dubbo-stub-mock.html
  • 相关阅读:
    Merlin 的魔力: SpringLayout 管理器
    setOpaque(true);设置控件不透明
    运用 BoxLayout 进行 Swing 控件布局
    李洪强iOS开发本人集成环信的经验总结_02_基本配置
    李洪强iOS开发之-PCH文件的配置
    李洪强iOS开发本人集成环信的经验总结_01环信SDK的导入
    iOS开发UI篇—Quartz2D使用(矩阵操作)
    iOS开发UI篇—Quartz2D使用(图形上下文栈)
    iOS开发UI篇—Quartz2D简单使用(二)
    iOS开发UI篇—Quartz2D简单使用(一)
  • 原文地址:https://www.cnblogs.com/hyry/p/12067497.html
Copyright © 2011-2022 走看看