dubbo 服务提供端与消费端应用的搭建(二)

####3.2基于 Dubbo API 方式的服务提供方与消费方搭建
#####基于Dubbo API 方式的服务提供方搭建
源码点这里
其中 Provider 模块为服务提供者,里面 TestProviderApi 是基于 Dubbo API 的服务提供,UserServiceImpl 为服务实现类。
首先需要在 Provider 模块里面引入 api 模块,这个不变。
然后实现 UserService 接口为 UserServiceImpl,这个也不变。
再接着编写 Dubbo API 服务提供测试代码 TestProviderApi,代码如下:

public class TestProviderAPI {

    public static void main(String [] args){

        try{
            UserService userService = new UserServiceImpl();

            ApplicationConfig appConfig = new ApplicationConfig();
            appConfig.setName("dubboProvider");

            RegistryConfig rConfig = new RegistryConfig();
            rConfig.setAddress("127.0.0.1:2181");
            rConfig.setProtocol("zookeeper");

            ProtocolConfig pConfig = new ProtocolConfig();
            pConfig.setName("dubbo");
            pConfig.setPort(20880);

            MonitorConfig mConfig = new MonitorConfig();
            mConfig.setProtocol("registry");

            // 此实例很重,封装了与注册中心的连接,请自行缓存,否则可能造成内存和连接泄漏
            ServiceConfig<UserService> sConfig = new ServiceConfig<UserService>();

            sConfig.setApplication(appConfig);
            sConfig.setRegistry(rConfig);// 多个注册中心可以用setRegistries()
            sConfig.setProtocol(pConfig);// 多个协议可以用setProtocols()
            sConfig.setMonitor(mConfig);

            sConfig.setInterface(UserService.class);
            sConfig.setGroup("dubbo");
            sConfig.setVersion("1.0.0");
            sConfig.setTimeout(3000);
            sConfig.setRef(userService);

            sConfig.export();

            Thread.currentThread().join();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

#####基于 Dubbo API 方式的服务消费方搭建
其中 Consumer 模块为服务消费者,里面 TestConsumerApi 是基于 Dubbo API 方式的服务调用。
首先需要在 Consumer 模块里面引入 api 模块,这个不变。
编写基于 Dubbo API 消费服务的测试类 TestConsumerApi,代码如下:

public class TestConsumerAPI {

    public static void main(String [] args){

        try{
            ApplicationConfig aConfig = new ApplicationConfig();
            aConfig.setName("dubboConsumer");

            RegistryConfig rConfig = new RegistryConfig();
            rConfig.setProtocol("zookeeper");
            rConfig.setAddress("127.0.0.1:2181");

            MonitorConfig mConfig  = new MonitorConfig();
            mConfig.setProtocol("registry");

            // 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
            ReferenceConfig<UserService> referenceConfig = new ReferenceConfig<UserService>();
            referenceConfig.setInterface(UserService.class);
            referenceConfig.setGroup("dubbo");
            referenceConfig.setVersion("1.0.0");
            referenceConfig.setTimeout(3000);
            referenceConfig.setInjvm(false);

            referenceConfig.setApplication(aConfig);
            referenceConfig.setRegistry(rConfig); // 多个注册中心可以用setRegistries()
            referenceConfig.setMonitor(mConfig);


            UserService userService = referenceConfig.get();
            System.out.println(userService.sayHello("yangzhaoApi"));

            Thread.currentThread().join();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

}

这里写图片描述

####3.3服务消费端泛化调用与异步调用
#####服务消费端泛化调用
前面我们讲解到,基于 Spring 和基于 Dubbo API 方式搭建简单的分布式系统时,服务消费端引入了一个 api 二方包,里面存放着服务提供端提供的所有接口类,之所以需要引入接口类是因为服务消费端一般是基于接口使用 JDK 代理实现远程调用的。
泛化接口调用方式主要在服务消费端没有 API 接口类及模型类元(比如入参和出参的 POJO 类)的情况下使用。其参数及返回值中没有对应的 POJO 类,所以所有 POJO 均转换为 Map 表示。使用泛化调用时候服务消费模块不再需要引入 api二方包。
下面基于 Dubbo API 实现异步调用,在 Consumer 模块里面 TestConsumerApiGeneric 是泛化调用的方式,代码如下:


    public static void main (String [] args){

        ApplicationConfig aConfig = new ApplicationConfig();
        aConfig.setName("dubboConsumer");

        RegistryConfig rConfig = new RegistryConfig();
        rConfig.setAddress("127.0.0.1:2181");
        rConfig.setProtocol("zookeeper");

        ReferenceConfig<GenericService> referenceConfig = new ReferenceConfig<GenericService>();
        referenceConfig.setApplication(aConfig);
        referenceConfig.setRegistry(rConfig);
        referenceConfig.setTimeout(3000);
        referenceConfig.setGroup("dubbo");
        referenceConfig.setVersion("1.0.0");

        referenceConfig.setInterface("com.dubbo.testSpring.UserService");
        referenceConfig.setGeneric(true);

        GenericService userService = referenceConfig.get();
        Object res = userService.$invoke("sayHello",new String[]{"java.lang.String"},new Object[]{"yangzhao3"});
        System.out.println(res);

        Map<String,Object> map = new HashMap<String,Object>();
        map.put("class","com.dubbo.provide.PersonImpl");// 注意:如果参数类型是接口,或者List等丢失泛型,可通过class属性指定类型。
        map.put("name","yangzhao4");
        map.put("passWord","123456");
        Object resPerson = userService.$invoke("sayPerson",new String[]{"com.dubbo.testSpring.Person"},new Object[]{map});
        System.out.println(resPerson);

    }
}

这里写图片描述

#####服务消费端异步调用
无论前面我们讲解的正常调用还是泛化调用,都是同步调用,也就是服务消费方发起一个远程调用后,调用线程要被阻塞挂起,直到服务提供方返回。

本节讲解下服务消费端异步调用,异步调用是指服务消费方发起一个远程调用后,不等服务提供方返回结果,调用方法就返回了,也就是当前线程不会被阻塞,这就允许调用方同时调用多个远程方法。


public class TestConsumerAsync {

    public static void main(String [] args){
        try{
            ApplicationConfig applicationConfig = new ApplicationConfig();
            applicationConfig.setName("dubboConsumer");

            RegistryConfig registryConfig = new RegistryConfig();
            registryConfig.setProtocol("zookeeper");
            registryConfig.setAddress("127.0.0.1:2181");

            ReferenceConfig<UserService> referenceConfig = new ReferenceConfig<UserService>();

            referenceConfig.setApplication(applicationConfig);
            referenceConfig.setRegistry(registryConfig);
            referenceConfig.setInterface(UserService.class);
            referenceConfig.setGroup("dubbo");
            referenceConfig.setVersion("1.0.0");
            referenceConfig.setTimeout(3000);

            referenceConfig.setAsync(true);

            UserService userService = referenceConfig.get();

            long beginTime = System.currentTimeMillis();
            
            System.out.println(userService.sayHello("yangzhao001"));//因为异步调用,此处返回null

           
            Future<String> userServiceFutureOne  = RpcContext.getContext().getFuture(); // 拿到调用的Future引用,当结果返回后,会被通知和设置到此Future
            System.out.println(userServiceFutureOne.get());//阻塞到get方法,等待结果返回
            
            System.out.println(userService.sayHello("yangzhao002"));//因为异步调用,此处返回null
            
            Future<String> userServiceFutureTwo  = RpcContext.getContext().getFuture();// 拿到调用的Future引用,当结果返回后,会被通知和设置到此Future
            System.out.println(userServiceFutureTwo.get());//阻塞到get方法,等待结果返回
            long endTime = System.currentTimeMillis();

            System.out.println("cost:"+(endTime-beginTime));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

这里写图片描述

其中代码输出 null,说明开启异步调用后调用方直接返回 null。

异步调用是基于 NIO 的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对调用不同的服务使用不同线程来说开销较小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值