You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2019/04/18 16:03:29 UTC

[incubator-dubbo-website] branch asf-site updated: update async blog

This is an automated email from the ASF dual-hosted git repository.

liujun 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 6072502  update async blog
6072502 is described below

commit 6072502649fdbbfec610b16b40848bf78cf5d43d
Author: ken.lj <ke...@gmail.com>
AuthorDate: Fri Apr 19 00:03:16 2019 +0800

    update async blog
---
 blog/zh-cn/dubbo-new-async.md | 127 +++++++++++++++++-------------------------
 1 file changed, 50 insertions(+), 77 deletions(-)

diff --git a/blog/zh-cn/dubbo-new-async.md b/blog/zh-cn/dubbo-new-async.md
index 6735c58..ce75d03 100644
--- a/blog/zh-cn/dubbo-new-async.md
+++ b/blog/zh-cn/dubbo-new-async.md
@@ -9,6 +9,16 @@ description: 本文回顾了 2.6.x 版本的异步实现,然后引出了 2.7.0
 
 基于Dubbo实现全异步编程,是在2.7.0版本中对现有异步方式增强后新引入的功能。本文先是回顾2.6.x及之前版本对异步的支持情况及存在的问题,引出了2.7.0版本基于CompletableFuture做了哪些针对性的增强,通过几个示例详细阐述了增强后的异步编程的使用方式,最后总结了引入异步模式带来的新问题及Dubbo的解决方法。通过阅读这篇文章,可以很容易的基于Dubbo2.7.0+版本实现一个全异步的远程服务调用链路。
 
+从3.0.0版本开始,Dubbo框架提供了对Reactive编程范式的支持,除了编程接口之外,在跨进程的RPC通信中引入了Reactive的语义。如果你所在的环境需要使用Reactive编程范式,或者你的RPC调用需要支持流式传输,请参考发布在阿里巴巴中间件公众号的[响应式编程支持]()相关文章。注意,你可能并不是总需要Reactive的语义,尤其是在RPC的场景,CompletableFuture本身也能带给你Reactive模式的编程模型,在选择Reactive(RxJava之类)而不是理解和编程成本更低的CompletableFuture前,请尝试关注以下问题:
+1. 你是请求/相应是一次性传输还是流式传输,一个明显特征是数据类型是 `List<String>` 还是 `Stream<String>`
+2. 你是否需要RPC请求可以是Cold,在subscribe后触发,CompletableFuture总是hot的
+3. 你的依赖的编程上下文中是否已经在大量使用Reactive的编程接口
+4. 你是否需要Rx框架提供的更丰富的Operator,而这点和1又是密切相关的
+
+关于参数回调,其本质上是一种服务端的数据推送能力,这是终端应用很常见的一种需求,关于这部分的重构计划,不在本文讨论范围。
+                                                                                                                         
+
+
 ## 2.6.x版本之前的异步方式
 
 在2.6.x及之前的版本提供了一定的异步编程能力,包括Consumer端[异步调用](http://dubbo.apache.org/zh-cn/docs/user/demos/async-call.html)、[参数回调](http://dubbo.apache.org/zh-cn/docs/user/demos/callback-parameter.html)、[事件通知](http://dubbo.apache.org/zh-cn/docs/user/demos/events-notify.html)等,在上面的文档链接中有关于使用方式的简单介绍和Demo。
@@ -91,11 +101,11 @@ Dubbo在2.7.0版本已经升级了对Java 8的支持,同时基于CompletableFu
 
    
 
-2. 如果你不想将接口的返回值定义为Future类型,或者存在定义好的同步类型接口,则可以额外定义一个异步接口并提供Future类型的方法。
+2. 如果你不想将接口的返回值定义为Future类型,或者存在定义好的同步类型接口,则可以选择重载原始方法并为新方法定义CompletableFuture类型返回值。
 
    
 
-   ```
+   ```java
    public interface GreetingsService {
        String sayHi(String name);
    }
@@ -103,24 +113,25 @@ Dubbo在2.7.0版本已经升级了对Java 8的支持,同时基于CompletableFu
 
    
 
-   ```
-   @AsyncFor(AsyncService.class)
-   public interface GrettingServiceAsync extends GreetingsService {
-       CompletableFuture<String> sayHiAsync(String name);
+   ```java
+   public interface GreetingsService {
+       String sayHi(String name);
+       // 为了保证方法级服务治理规则依然有效,建议保持方法名不变: sayHi
+       // 使用default实现,避免给服务端提供者带来额外实现成本
+       // boolean placeHoler只是为了实现重载而增加,只要Java语法规则允许,你可以使用任何方法重载手段
+       default CompletableFuture<String> sayHi(String name, boolean placeHolder) {
+         return CompletableFuture.completedFuture(sayHello(name));
+       }
    }
    ```
 
    
 
-   这样,Provider可以只实现sayHi方法;而Consumer通过直接调用sayHiAsync可以拿到一个Future实例,Dubbo框架在Provider端会自动转换为对sayHi方法的调用。
-
+   这样,Provider依然可以只实现sayHi方法;而Consumer通过直接调用新增的sayHi重载方法可以拿到一个Future实例。
    
 
-   为每个同步方法提供一个异步方法定义会比较麻烦,更进一步的,利用Dubbo生态中的[Annotation Processor实现](https://github.com/dubbo/dubbo-async-processor),可以自动帮我们自动生成异步方法定义。
-
-3. 同样的,如果你的原始接口定义不是Future类型的返回值,Provider端异步也提供了类似Servlet3.0里的Async Servlet的编程接口: `RpcContext.startAsync()`。
-
-   
+3. 如果你的原始接口定义是同步的,这时要实现Provider端异步,则可以使用AsyncContext(类似Servlet 3.0里的AsyncContext的编程接口)。注意:在已有CompletabeFuture返回类型的接口上,不建议再使用AsyncContext,请直接利用CompletableFuture带来的异步能力。
+ 
 
    ```
    public interface AsyncService {
@@ -261,9 +272,9 @@ CompletableFuture类型的接口既可以用作同步调用,也可以实现Con
 
    `CompletableFuture<String> future = asyncService.sayHello("async call request");`很自然的返回了Future示例,这样就实现了Consumer端的异步服务调用。
 
-## 示例2:同步接口使用Annotation Processor
+## 示例2:重载同步接口
 
-这个示例演示了如何在只定义同步接口的基础上,使用Annotation Processor实现Consumer端异步方服务调用,具体代码参见地址[dubbo-samples-async-generated-future](https://github.com/apache/incubator-dubbo-samples/tree/master/dubbo-samples-async/dubbo-samples-async-generated-future)
+这个示例演示了如何在同步接口的基础上,通过增加重载方法实现消费端的异步调用,具体代码参见地址[dubbo-samples-async-generated-future](https://github.com/apache/incubator-dubbo-samples/tree/3.x/dubbo-samples-async/dubbo-samples-async-generated-future)
 
 1. 定义接口
 
@@ -278,55 +289,19 @@ CompletableFuture类型的接口既可以用作同步调用,也可以实现Con
 
    
 
-   这是一个普通的Dubbo服务接口定义。注意,使用Annotation Processor要加上@DubboAsync注解。
-
-   
-
-   ```
-   <dependency>
-       <groupId>com.alibaba</groupId>
-       <artifactId>dubbo-async-processer</artifactId>
-       <version>1.0.0-SNAPSHOT</version>
-   </dependency>
-   <plugin>
-       <groupId>org.apache.maven.plugins</groupId>
-       <artifactId>maven-compiler-plugin</artifactId>
-       <version>3.7.0</version>
-       <configuration>
-           <source>1.8</source>
-           <target>1.8</target>
-           <annotationProcessorPaths>
-               <path>
-                   <groupId>com.alibaba</groupId>
-                   <artifactId>dubbo-async-processer</artifactId>
-                   <version>1.0.0-SNAPSHOT</version>
-               </path>
-           </annotationProcessorPaths>
-       </configuration>
-   </plugin>
-   ```
-
-   
-
-   以上是引入dubbo-async-processer处理器的Maven依赖,通常定义接口(提供API)的开发者将以上依赖加到工程中,这样在做API打包的时候,API中会自动生成以下接口定义:
-
-   
-
-   ```
-   /**
-   * Generated by dubbo-async-processer
-   */
-   package com.alibaba.dubbo.samples.api;
-   import java.util.concurrent.CompletableFuture;
-   @javax.annotation.Generated("com.alibaba.dubbo.async.processor.AsyncAnnotationProcessor")
-   @org.apache.dubbo.common.config.AsyncFor(com.alibaba.dubbo.samples.api.GreetingsService.class)
-   public interface GreetingsServiceAsync extends GreetingsService {
-   CompletableFuture<java.lang.String> sayHiAsync(java.lang.String name);
-   }
-   ```
-
-   
+   修改接口,增加重载方法
 
+    ```java
+    public interface GreetingsService {
+        String sayHi(String name);
+      
+        default CompletableFuture<String> sayHi(String name, boolean placeHolder) {
+          return CompletableFuture.completedFuture(sayHello(name));
+        }
+    }
+    ```
+    
+    
    
 
 2. Provider端
@@ -366,7 +341,7 @@ CompletableFuture类型的接口既可以用作同步调用,也可以实现Con
    
 
    ```
-    <dubbo:reference id="greetingsService" interface="com.alibaba.dubbo.samples.api.GreetingsServiceAsync"/>
+    <dubbo:reference id="greetingsService" interface="com.alibaba.dubbo.samples.api.GreetingsService"/>
    ```
 
    
@@ -384,8 +359,8 @@ CompletableFuture类型的接口既可以用作同步调用,也可以实现Con
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/async-consumer.xml"});
            context.start();
    
-           GreetingsServiceAsync greetingsService = (GreetingsServiceAsync) context.getBean("greetingsService");
-           CompletableFuture<String> future = greetingsService.sayHiAsync("async call reqeust");
+           GreetingsService greetingsService = (GreetingsService) context.getBean("greetingsService");
+           CompletableFuture<String> future = greetingsService.sayHi("async call reqeust");
            System.out.println("async call ret :" + future.get());
         
            System.in.read();
@@ -394,11 +369,11 @@ CompletableFuture类型的接口既可以用作同步调用,也可以实现Con
 
    
 
-   这样,我们就可以直接使用`CompletableFuture<String> future = greetingsService.sayHiAsync("async call reqeust");`,直接返回CompletableFuture。
+   这样,我们就可以直接使用`CompletableFuture<String> future = greetingsService.sayHi("async call reqeust");`,直接返回CompletableFuture。
 
 ## 示例3:使用AsyncContext
 
-本示例演示了如何在同步接口的基础上,通过AsyncContext实现Provider端异步执行,示例代码参见[dubbo-samples-async-provider](https://github.com/apache/incubator-dubbo-samples/tree/master/dubbo-samples-async/dubbo-samples-async-provider)。
+本示例演示了如何在同步接口的基础上,通过AsyncContext实现Provider端异步执行,示例代码参见[dubbo-samples-async-provider](https://github.com/apache/incubator-dubbo-samples/tree/3.x/dubbo-samples-async/dubbo-samples-async-provider)。
 
 1. 定义接口
 
@@ -414,7 +389,7 @@ CompletableFuture类型的接口既可以用作同步调用,也可以实现Con
 
    
 
-2. Provider端
+2. Provider端,和普通provider端配置完全一致
 
    
 
@@ -429,10 +404,6 @@ CompletableFuture类型的接口既可以用作同步调用,也可以实现Con
 
    
 
-   注意,要加上`async="true"`表明这是一个开启Provider端异步执行的服务。
-
-   
-
    - 异步执行实现
 
    
@@ -501,17 +472,17 @@ CompletableFuture类型的接口既可以用作同步调用,也可以实现Con
 
 以下是一个扩展Filter并支持异步Filter链的例子
 
-```
+```java
 @Activate(group = {Constants.PROVIDER, Constants.CONSUMER})
-public class AsyncPostprocessFilter extends AbstractPostProcessFilter {
+public class AsyncPostprocessFilter implements Filter {
 
     @Override
     public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
-        return postProcessResult(invoker.invoke(invocation), invoker, invocation);
+        return invoker.invoke(invoker, invocation);
     }
 
     @Override
-    protected Result doPostProcess(Result result, Invoker<?> invoker, Invocation invocation) {
+    public Result onResponse(Result result, Invoker<?> invoker, Invocation invocation) {
         System.out.println("Filter get the return value: " + result.getValue());
         return result;
     }
@@ -520,6 +491,8 @@ public class AsyncPostprocessFilter extends AbstractPostProcessFilter {
 
 ### 上下文传递
 
+这里的上下文问题主要是指在提供端异步的场景。
+
 当前我们考虑的上下文主要是指保存在RpcContext中的数据,大多数场景是需要用户在切换业务线程前自己完成Context的传递。
 
 ```