ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Dubbo系列<7>-服务消费端泛化调用与异步调用

2020-12-14 17:51:10  阅读:155  来源: 互联网

标签:Dubbo 调用 服务 泛化 异步 password String


服务消费端泛化调用

前面我们搭建了基于 Spring 和Dubbo API 方式简单的简单调用。服务消费端引入了一个 SDK 二方包(api.jar),里面存放着服务提供端提供的所有接口类,之所以需要引入接口类是因为服务消费端一般是基于接口使用 JDK 代理实现远程调用的。

泛化接口调用方式主要在服务消费端没有 API 接口类及模型类元(比如入参和出参的 POJO 类)的情况下使用。其参数及返回值中没有对应的 POJO 类,所以所有 POJO 均转换为 Map 表示。使用泛化调用时候服务消费模块不再需要引入 SDK 二方包。

下面基于 Dubbo API 实现异步调用,在 Consumer 模块里面 TestConsumerApiGeneric 是泛化调用的方式,代码如下:

上面代码中,由于 sayHello 的参数是 String,没有很好的体现参数转换为 Map,下面我们具体来说下 POJO 参数转换 Map 的含义。

比如服务提供者提供的一个接口的 testPojo(Person person) 方法的参数为如下所示:

package com.test;public class PersonImpl implements Person {private String name;private String password;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}

则 POJO 数据:

Person person = new PersonImpl();person.setName("lawt");person.setPassword("password");

正常情况下调用接口是使用:

servicePerson.testPojo(person);

泛化调用下需要首先转换 person 为 Map,如下表示:

Map<String, Object> map = new HashMap<String, Object>();// 注意:如果参数类型是接口,或者List等丢失泛型,可通过class属性指定类型。map.put("class", "com.test.PersonImpl");map.put("name", "lawt");map.put("password", "password");

然后使用下面方法进行泛化调用:

servicePerson.$invoke("testPojo", new String[]{"com.tian.dubbo.domain.Person"}, new Object[]{map});

泛化调用通常用于框架集成,比如:实现一个通用的服务测试框架,可通过 GenericService 调用所有服务实现,而不需要依赖服务实现方提供的接口类以及接口的入参和出参的 POJO 类。

服务消费端异步调用

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

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

在 Consumer 模块里面 TestConsumerAsync 是泛化调用,代码如下:

public class TestConsumerAsync {    public static void main(String[] args) throws InterruptedException, ExecutionException {        // 当前应用配置       ApplicationConfig application = new ApplicationConfig();       application.setName("dubboConsumer");        // 连接注册中心配置       RegistryConfig registry = new RegistryConfig();       registry.setAddress("127.0.0.1:2181");       registry.setProtocol("zookeeper");        // 引用远程服务       ReferenceConfig<UserServiceBo> reference = new ReferenceConfig<UserServiceBo>();       reference.setApplication(application);       reference.setRegistry(registry);       reference.setInterface(UserServiceBo.class);       reference.setVersion("1.0.0");       reference.setTimeout(3000);        //(1)设置为异步调用       reference.setAsync(true);        // 和本地bean一样使用xxxService       UserServiceBo userService = reference.get();      long startTime = System.currentTimeMillis() / 1000;        // (2)因为异步调用,此处返回null       System.out.println(userService.sayHello("哈哈哈"));        // 拿到调用的Future引用,当结果返回后,会被通知和设置到此Future            Future<String> userServiceFutureOne = RpcContext.getContext().getFuture();        // (3)因为异步调用,此处返回null          System.out.println(userService.sayHello2("哈哈哈2"));        // 拿到调用的Future引用,当结果返回后,会被通知和设置到此Future            Future<String> userServiceFutureTwo = RpcContext.getContext().getFuture();        // (4)阻塞到get方法,等待结果返回             System.out.println(userServiceFutureOne.get());       System.out.println(userServiceFutureTwo.get());              long endTime = System.currentTimeMillis() / 1000;       System.out.println("costs:" + (endTime - startTime));   }}

运行上面代码,输出如下图所示:


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

输出 costs:2 说明异步调用生效了,因为 sayHello 和 sayHello2 方法内都 sleep 了2s,如果是顺序调用则会耗时至少4s,这里耗时2s说明两次调用是并发进行的。

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


标签:Dubbo,调用,服务,泛化,异步,password,String
来源: https://blog.51cto.com/10983206/2564051

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有