This is an automated email from the ASF dual-hosted git repository. jerrick pushed a commit to branch asf-site in repository https://gitbox.apache.org/repos/asf/incubator-dubbo-website.git
The following commit(s) were added to refs/heads/asf-site by this push: new 26eadb1 add blogs (#87) 26eadb1 is described below commit 26eadb158488a435e8af9ca2998313a1c0234f03 Author: Jerrick Zhu <diecui1...@gmail.com> AuthorDate: Fri Aug 10 16:14:53 2018 +0800 add blogs (#87) --- blog/zh-cn/dubbo-generic-invoke.md | 172 +++++++++++++++++++++++++++++++++++++ blog/zh-cn/dubbo-loadbalance.md | 0 blog/zh-cn/dubbo-new-async.md | 0 site_config/blog.js | 23 ++++- 4 files changed, 194 insertions(+), 1 deletion(-) diff --git a/blog/zh-cn/dubbo-generic-invoke.md b/blog/zh-cn/dubbo-generic-invoke.md new file mode 100644 index 0000000..c170c9b --- /dev/null +++ b/blog/zh-cn/dubbo-generic-invoke.md @@ -0,0 +1,172 @@ +# Dubbo的泛化调用 + +以下几种场景可以考虑使用泛化调用: + +- 服务测试平台 +- API 服务网关 + +泛化调用主要用于消费端没有 API 接口的情况;不需要引入接口 jar 包,而是直接通过 GenericService 接口来发起服务调用,参数及返回值中的所有 POJO 均用 `Map` 表示。泛化调用对于服务端无需关注,按正常服务进行暴露即可。 + +下面来看看消费端如何使用泛化调用进行服务调用。 + +#### 通过 Spring XML 配置进行泛化调用 + +在 Spring 配置申明 `generic="true"`,如: + +```xml +<dubbo:reference id="userService" interface="com.alibaba.dubbo.samples.generic.api.IUserService" generic="true"/> +``` + +需要使用的地方,通过强制类型转化为 GenericService 进行调用: + +```java +GenericService userService = (GenericService) context.getBean("userService"); +// primary param and return value +String name = (String) userService.$invoke("delete", new String[]{int.class.getName()}, new Object[]{1}); +System.out.println(name); +``` + +其中: + +1. GenericService 这个接口只有一个方法,名为 `$invoke`,它接受三个参数,分别为方法名、方法参数类型数组和参数值数组; +2. 对于方法参数类型数组 + 1. 如果是基本类型,如 int 或 long,可以使用 `int.class.getName()`获取其类型; + 2. 如果是基本类型数组,如 int[],则可以使用 `int[].class.getName()`; + 3. 如果是 POJO,则直接使用全类名,如 `com.alibaba.dubbo.samples.generic.api.Params`。 + +#### 通过 API 编程进行泛化调用 + +``` +ApplicationConfig application = new ApplicationConfig()ApplicationConfig application = new ApplicationConfig(); +application.setName("api-generic-consumer"); + +RegistryConfig registry = new RegistryConfig(); +registry.setAddress("zookeeper://127.0.0.1:2181"); + +application.setRegistry(registry); + +ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>(); +// 弱类型接口名 +reference.setInterface("com.alibaba.dubbo.samples.generic.api.IUserService"); +// 声明为泛化接口 +reference.setGeneric(true); + +reference.setApplication(application); + +// 用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口引用 +GenericService genericService = reference.get(); + +String name = (String) genericService.$invoke("delete", new String[]{int.class.getName()}, new Object[]{1}); +System.out.println(name); +``` + +通过 API 的方式,不需要像 XML 的方式需要提前将服务配置好,可以动态构建 ReferenceConfig;相对 XML 来说,API 的方式更常见。 + +#### 参数或返回值是 POJO 的场景 + +比如方法签名是 `User get(Params params);`其中 User 有 id 和 name 两个属性,Params 有 query 一个属性。 + +以下是消费端的调用代码: + +```java +String[] parameterTypes = new String[]{"com.alibaba.dubbo.samples.generic.api.Params"}; +Map<String, Object> params = new HashMap<String, Object>(); +param.put("class", "com.alibaba.dubbo.samples.generic.api.Params"); +param.put("query", "a=b"); +Object user = userService.$invoke("get", parameterTypes, new Object[]{param}); +System.out.println("sample one result: " + user); +``` + +上述代码的输出结果为: + +```shell +sample one result: {name=charles, id=1, class=com.alibaba.dubbo.samples.generic.api.User} +``` + +这里,Dubbo 框架会自动将 POJO 的返回值转换成 Map。可以看到,返回值 `user` 是一个 HashMap,里面分别存放了 name、id、class 三个 k/v。 + +#### 泛接口实现 + +泛接口实现方式主要用于服务端没有 API 接口的情况,参数及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成,如实现一个通用的远程服务 Mock 框架,可通过实现 GenericService 接口处理所有服务请求。 + +##### 服务端实现 GenericService + +```java +public class GenericServiceImpl implements GenericService { + @Override + public Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException { + if (method.equals("hi")) { + return "hi, " + args[0]; + } else if (method.equals("hello")) { + return "hello, " + args[0]; + } + + return "welcome"; + } +} +``` + +##### 服务端暴露服务 + +```java +ApplicationConfig application = new ApplicationConfig(); +application.setName("api-generic-provider"); + +RegistryConfig registry = new RegistryConfig(); +registry.setAddress("zookeeper://127.0.0.1:2181"); + +application.setRegistry(registry); + +GenericService genericService = new GenericServiceImpl(); + +ServiceConfig<GenericService> service = new ServiceConfig<GenericService>(); +service.setApplication(application); +service.setInterface("com.alibaba.dubbo.samples.generic.api.HelloService"); +service.setRef(genericService); +service.export(); + +ServiceConfig<GenericService> service2 = new ServiceConfig<GenericService>(); +service2.setApplication(application); +service2.setInterface("com.alibaba.dubbo.samples.generic.api.HiService"); +service2.setRef(genericService); +service2.export(); +``` + +同样,也可以使用 XML 配置的方式暴露服务;此时服务端是没有依赖 HiService 和 HelloService 这两个接口的。 + +##### 消费端进行服务调用 + +```java +ApplicationConfig application = new ApplicationConfig(); +application.setName("api-generic-consumer"); + +RegistryConfig registry = new RegistryConfig(); +registry.setAddress("zookeeper://127.0.0.1:2181"); + +application.setRegistry(registry); + +ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>(); +// 弱类型接口名 +reference.setInterface(HiService.class); +reference.setApplication(application); + +HiService hiService = (HiService) reference.get(); +System.out.println(hiService.hi("dubbo")); + +ReferenceConfig<GenericService> reference2 = new ReferenceConfig<GenericService>(); +// 弱类型接口名 +reference2.setInterface(HelloService.class); +reference2.setApplication(application); + +HelloService helloService = (HelloService) reference2.get(); +System.out.println(helloService.hello("community")); +``` + +同样,消费端也可以使用 XML 配置的方式引用服务,然后进行调用。这里可以看到调用方式为普通的服务调用,并非泛化调用。当然使用泛化调用也是可以的。 + +到这里为止,一个简易的服务 Mock 平台就成功上线了! + +#### 其他 + +* 本文介绍的泛化调用和泛接口实现,都是在原生的 `Dubbo` 协议之上的。在 2.6.2 版本之前,其他协议如 http/hessian 等是不支持泛化调用的,2.6.3 版本将会对这两个协议的泛化调用做支持。 +* 本文中提到的相关示例代码可以在 dubbo-samples中找到:https://github.com/dubbo/dubbo-samples/tree/master/dubbo-samples-generic \ No newline at end of file diff --git a/blog/zh-cn/dubbo-loadbalance.md b/blog/zh-cn/dubbo-loadbalance.md new file mode 100644 index 0000000..e69de29 diff --git a/blog/zh-cn/dubbo-new-async.md b/blog/zh-cn/dubbo-new-async.md new file mode 100644 index 0000000..e69de29 diff --git a/site_config/blog.js b/site_config/blog.js index 94ae9a0..5603eba 100644 --- a/site_config/blog.js +++ b/site_config/blog.js @@ -79,10 +79,31 @@ export default { barText: '博客', postsTitle: '所有文章', list: [ + { + title: '如何基于Dubbo实现全异步调用链', + author: '@chickenlj', + dateStr: 'August 10th, 2018', + desc: '本文回顾了 2.6.x 版本的异步实现,然后引出了 2.7.0 版本基于 CompletableFuture 的异步编程方式', + link: '/blog/dubbo-new-async.md', + }, + { + title: 'Dubbo的负载均衡', + author: '@leiwei', + dateStr: 'August 10th, 2018', + desc: '本文介绍了负载均衡的相关概念以及 Dubbo 中的负载均衡策略实现', + link: '/blog/dubbo-generic-invoke.md', + }, + { + title: 'Dubbo的泛化调用', + author: '@jerrick', + dateStr: 'August 10th, 2018', + desc: '本文介绍了 Dubbo 泛化调用的使用场景及相关示例', + link: '/blog/dubbo-generic-invoke.md', + }, { title: '如何准备一次Apache发布', author: '@chickenlj', - dateStr: 'August 8rd, 2018', + dateStr: 'August 8th, 2018', desc: '从如何搭建本地构建环境到如何发起投票,详细的介绍了Apache版本发布的完整流程', link: '/blog/Prepare-an-Apache-release.md', },