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 49917b0  build site
49917b0 is described below

commit 49917b01a478d041556bd69f1638897a085b5faa
Author: zhuyong <yong.z...@alibaba-inc.com>
AuthorDate: Wed Aug 15 13:10:19 2018 +0800

    build site
---
 build/blog.js                               |   2 +-
 en-us/blog/dubbo-new-async.html             | 416 ++++++++++++++++++++++++++++
 en-us/blog/dubbo-new-async.json             |   4 +
 en-us/blog/index.html                       |   2 +-
 en-us/blog/introduction-to-dubbo-spi-2.html | 388 ++++++++++++++++++++++++++
 en-us/blog/introduction-to-dubbo-spi-2.json |   4 +
 site_config/blog.js                         |  45 +--
 zh-cn/blog/dubbo-new-async.html             |   4 +-
 zh-cn/blog/dubbo-new-async.json             |   2 +-
 zh-cn/blog/index.html                       |   2 +-
 10 files changed, 841 insertions(+), 28 deletions(-)

diff --git a/build/blog.js b/build/blog.js
index 1349987..78543c8 100644
--- a/build/blog.js
+++ b/build/blog.js
@@ -3,4 +3,4 @@
   Licensed under the MIT License (MIT), see
   http://jedwatson.github.io/classnames
 */
-!function(){"use strict";function n(){for(var 
e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof 
r;if("string"===o||"number"===o)e.push(r);else 
if(Array.isArray(r)&&r.length){var a=n.apply(null,r);a&&e.push(a)}else 
if("object"===o)for(var u in r)i.call(r,u)&&r[u]&&e.push(u)}}return e.join(" 
")}var i={}.hasOwnProperty;void 
0!==e&&e.exports?(n.default=n,e.exports=n):(r=[],void 0!==(o=function(){return 
n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";funct [...]
\ No newline at end of file
+!function(){"use strict";function n(){for(var 
e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof 
r;if("string"===o||"number"===o)e.push(r);else 
if(Array.isArray(r)&&r.length){var a=n.apply(null,r);a&&e.push(a)}else 
if("object"===o)for(var u in r)i.call(r,u)&&r[u]&&e.push(u)}}return e.join(" 
")}var i={}.hasOwnProperty;void 
0!==e&&e.exports?(n.default=n,e.exports=n):(r=[],void 0!==(o=function(){return 
n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";funct [...]
\ No newline at end of file
diff --git a/en-us/blog/dubbo-new-async.html b/en-us/blog/dubbo-new-async.html
new file mode 100644
index 0000000..f4b28d6
--- /dev/null
+++ b/en-us/blog/dubbo-new-async.html
@@ -0,0 +1,416 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+       <meta charset="UTF-8">
+       <meta name="viewport" content="width=device-width, initial-scale=1.0, 
maximum-scale=1.0, user-scalable=no">
+       <meta name="keywords" content="dubbo-new-async" />
+       <meta name="description" content="dubbo-new-async" />
+       <!-- 网页标签标题 -->
+       <title>dubbo-new-async</title>
+       <link rel="shortcut icon" href="/img/dubbo.ico"/>
+       <link rel="stylesheet" href="/build/blogDetail.css" />
+</head>
+<body>
+       <div id="root"><div class="blog-detail-page" data-reactroot="" 
data-reactid="1" data-react-checksum="773733418"><header 
class="header-container header-container-normal" data-reactid="2"><div 
class="header-body" data-reactid="3"><a href="/en-us/index.html" 
data-reactid="4"><img class="logo" src="/img/dubbo_colorful.png" 
data-reactid="5"/></a><span class="language-switch language-switch-normal" 
data-reactid="6">中</span><div class="header-menu" data-reactid="7"><img 
class="header-menu-togg [...]
+<p>Implementing the full asynchronous programming based on Dubbo, which is a 
new feature introduced in version 2.7.0 after the enhancement of the existing 
asynchronous mode.This article first reviews the supported functions and 
existing problems of asynchronization in 2.6.x and earlier versions, and 
introduces the targeted enhancements based on CompletableFuture in version 
2.7.0. Then, the use of enhanced asynchronous programming is elaborated through 
several examples. Finally, it summar [...]
+<h2>Asynchronous mode before version 2.6.x</h2>
+<p>Dubbo Provides some asynchronous programming capabilities in 2.6.x and 
earlier versions, including <a 
href="http://dubbo.apache.org/books/dubbo-user-book/demos/async-call.html";>Asynchronous
 Call</a>, <a 
href="http://dubbo.apache.org/books/dubbo-user-book/demos/callback-parameter.html";>Parameter
 Callback</a> and <a 
href="http://dubbo.apache.org/books/dubbo-user-book/demos/events-notify.html";>Event
 Notification</a> on Consumer side. There are some brief introductions to the 
usage and De [...]
+<p>But the current asynchronous method has the following problems:</p>
+<ul>
+<li>Methods to access Future object are not direct enough.</li>
+<li>Future interface cannot implement automatic callback. Customized 
ResponseFuture class could implement callback, however it only supports limited 
asynchronous scenes. For example, it does not support mutual coordination or 
combination between Future objects.</li>
+<li>Asynchronization on Provider side is not supported.</li>
+</ul>
+<p>Take the asynchronous method of Consumer side as an example:</p>
+<ol>
+<li>Define a original synchronous interface and add the declaration to support 
asynchronous calls.</li>
+</ol>
+<pre><code>public interface FooService {
+    String findFoo(String name);
+}
+</code></pre>
+<pre><code>&lt;dubbo:reference id=&quot;fooService&quot; 
interface=&quot;com.alibaba.foo.FooService&quot;&gt;
+      &lt;dubbo:method name=&quot;findFoo&quot; async=&quot;true&quot; /&gt;
+&lt;/dubbo:reference&gt;
+</code></pre>
+<ol start="2">
+<li>Obtain Future object through RpcContext.</li>
+</ol>
+<pre><code>// this call will return null immediately
+fooService.findFoo(fooId);
+// Obtain the Future instance. When the result is returned, Future instance 
will be notified and the result will be set to Future instance.
+Future&lt;Foo&gt; fooFuture = RpcContext.getContext().getFuture();
+fooFuture.get();
+</code></pre>
+<p>or</p>
+<pre><code>// this call will return null immediately
+fooService.findFoo(fooId);
+// get Dubbo's built-in ResponseFuture, and set the callback
+ResponseFuture future = 
((FutureAdapter)RpcContext.getContext().getFuture()).getFuture();
+future.setCallback(new ResponseCallback() {
+    @Override
+    public void done(Object response) {
+        System.out.print(response);
+    }
+
+    @Override
+    public void caught(Throwable exception) {
+        exception.printStackTrace();
+    }
+});
+</code></pre>
+<p>From this simple example, we can see there are some inconveniences in 
use:</p>
+<ol>
+<li>The synchronization interface of findFoo cannot directly return a Future 
object representing the asynchronous result, which is further obtained through 
RpcContext.</li>
+<li>Future object can only be obtained from get method that will block until 
getting the result.</li>
+<li>Callback can be set by getting the built-in ResponseFuture interface. 
However, the API to obtain ResponseFuture is not convenient enough to support 
other asynchronous scenes except callback. For example, it does not support the 
scene where multiple Future objects work together.</li>
+</ol>
+<h2>Enhancement based on CompletableFuture in version 2.7.0</h2>
+<p>People who understand the evolution history of Future in Java should know 
that the Future used in Dubbo 2.6.x and earlier versions is introduced in Java 
5, so there are some problems in function design.The CompletableFuture 
introduced in Java 8 further enriches the Future interface and solves these 
problems well.</p>
+<p>Support for Java 8 has been upgraded in Dubbo 2.7.0, and Dubbo has enhanced 
the current asynchronous functionality based on CompletableFuture.</p>
+<ol>
+<li>
+<p>Now it supports direct definition of service interfaces that return 
CompletableFuture. Through these interfaces, we can implement asynchronous 
programming on both Consumer side and Provider side more naturally.</p>
+<pre><code>public interface AsyncService {
+    CompletableFuture&lt;String&gt; sayHello(String name);
+}
+</code></pre>
+</li>
+<li>
+<p>If you don't want to define the return value of the interface as a Future 
object, or if there is a defined synchronization interface, you can 
additionally define an asynchronous interface and provide a method to return a 
Future object.</p>
+<pre><code>public interface AsyncService {
+    CompletableFuture&lt;String&gt; sayHello(String name);
+}
+</code></pre>
+<pre><code>@AsyncFor(AsyncService.class)
+public interface GrettingServiceAsync extends GreetingsService {
+    CompletableFuture&lt;String&gt; sayHiAsync(String name);
+}
+</code></pre>
+<p>In this way, Provider can only implement the sayHi method. The Consumer can 
get a Future instance by directly calling sayHiAsync, and Dubbo framework will 
convert it to a call to the sayHi method on the Provider side automatically.</p>
+<p>Providing an asynchronous method definition for each synchronization method 
can be inconvenient. Further, using <a 
href="https://github.com/dubbo/dubbo-async-processor";>Annotation Processor 
implementation</a> in the Dubbo ecosystem can automatically generate 
asynchronous method definitions for us.</p>
+</li>
+<li>
+<p>Similarly, if your original interface definition doesn't return a Future 
object, the Provider side also provides a programming interface similar to the 
Async Servlet in Servlet 3.0 to support asynchronization : 
<code>RpcContext.startAsync()</code>.</p>
+<pre><code>public interface AsyncService {
+    String sayHello(String name);
+}
+</code></pre>
+<pre><code>public class AsyncServiceImpl implements AsyncService {
+    public String sayHello(String name) {
+        final AsyncContext asyncContext = RpcContext.startAsync();
+        new Thread(() -&gt; {
+            asyncContext.write(&quot;Hello &quot; + name + &quot;, response 
from provider.&quot;);
+        }).start();
+        return null;
+    }
+}
+</code></pre>
+<p>At the beginning of the method body, it starts asynchronization by running 
<code>RpcContext.startAsync()</code> , and it starts a new thread to execute 
the business logic asynchronously. After the time-consuming operation is 
completed, the result is written back by <code>asyncContext.write</code>.</p>
+</li>
+<li>
+<p>RpcContext returns CompletableFuture directly.</p>
+<pre><code>CompletableFuture&lt;String&gt; f = 
RpcContext.getContext().getCompletableFuture();
+</code></pre>
+</li>
+</ol>
+<p>All of the above enhancements are based on the compatibility with existing 
asynchronous programming, so asynchronous programs written based on 2.6.x 
versions can be successfully compiled without any modification.</p>
+<p>Next, let's illustrate how to implement a fully asynchronous Dubbo service 
call chain through a few examples.</p>
+<h2>example 1:CompletableFuture interface</h2>
+<p>CompletableFuture interface can be used both for a synchronous call and for 
an asynchronous call on Consumer or Provider side. This example implements 
asynchronous calls between Consumer and Provider sides. Code link <a 
href="https://github.com/dubbo/dubbo-samples/tree/samples-for-2.7.0-SNAPSHOT/dubbo-samples-async-original-future";>dubbo-samples-async-original-future</a>.</p>
+<ol>
+<li>
+<p>Interface definition</p>
+<pre><code>public interface AsyncService {
+    CompletableFuture&lt;String&gt; sayHello(String name);
+}
+</code></pre>
+<p>Note that the return type of this interface is 
<code>CompletableFuture&lt;String&gt;</code>.</p>
+</li>
+<li>
+<p>Provider Side</p>
+<ul>
+<li>
+<p>Implementation</p>
+<pre><code>public class AsyncServiceImpl implements AsyncService {
+    public CompletableFuture&lt;String&gt; sayHello(String name) {
+        return CompletableFuture.supplyAsync(() -&gt; {
+            try {
+                Thread.sleep(5000);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            return &quot;async response from provider.&quot;;
+        });
+    }
+}
+</code></pre>
+<p>We can see that the business code is switched to be executed in the new 
thread by supplyAsync, so the Provider side is asynchronous.</p>
+</li>
+<li>
+<p>Config</p>
+<pre><code>&lt;bean id=&quot;asyncService&quot; 
class=&quot;com.alibaba.dubbo.samples.async.impl.AsyncServiceImpl&quot;/&gt;
+&lt;dubbo:service 
interface=&quot;com.alibaba.dubbo.samples.async.api.AsyncService&quot; 
ref=&quot;asyncService&quot;/&gt;
+</code></pre>
+<p>The Config is the same as the original interface.</p>
+</li>
+</ul>
+</li>
+<li>
+<p>Consumer Side</p>
+<ul>
+<li>Config</li>
+</ul>
+<pre><code>&lt;dubbo:reference id=&quot;asyncService&quot; 
timeout=&quot;10000&quot; 
interface=&quot;com.alibaba.dubbo.samples.async.api.AsyncService&quot;/&gt;
+</code></pre>
+<p>​   The Config is the same as the original interface.</p>
+<ul>
+<li>Call remote service</li>
+</ul>
+<pre><code>public static void main(String[] args) throws Exception {
+        ClassPathXmlApplicationContext context = new 
ClassPathXmlApplicationContext(new 
String[]{&quot;META-INF/spring/async-consumer.xml&quot;});
+        context.start();
+        final AsyncService asyncService = (AsyncService) 
context.getBean(&quot;asyncService&quot;);
+    
+        CompletableFuture&lt;String&gt; future = 
asyncService.sayHello(&quot;async call request&quot;);
+        future.whenComplete((v, t) -&gt; {
+            if (t != null) {
+                t.printStackTrace();
+            } else {
+                System.out.println(&quot;Response: &quot; + v);
+            }
+        });
+        System.out.println(&quot;Executed before response return.&quot;);
+        System.in.read();
+    }
+</code></pre>
+<p><code>CompletableFuture&lt;String&gt; future = 
asyncService.sayHello(&quot;async call request&quot;);</code>It is convenient 
to return the Future instance, which implements the asynchronous service call 
on the Consumer side.</p>
+</li>
+</ol>
+<h2>Example 2:Synchronous interface uses Annotation Processor</h2>
+<p>This example demonstrates how to implement the Consumer-side asynchronous 
service call using the Annotation Processor based on the original synchronous 
interface. Code link <a 
href="https://github.com/dubbo/dubbo-samples/tree/samples-for-2.7.0-SNAPSHOT/dubbo-samples-async-generated-future";>dubbo-samples-async-generated-future</a>.</p>
+<ol>
+<li>
+<p>Interface definition</p>
+<pre><code>@DubboAsync
+public interface GreetingsService {
+    String sayHi(String name);
+}
+</code></pre>
+<p>This is a generic definition of the Dubbo service interface. Note that add 
the @DubboAsync annotation when using Annotation Processor.</p>
+<pre><code>&lt;dependency&gt;
+    &lt;groupId&gt;com.alibaba&lt;/groupId&gt;
+    &lt;artifactId&gt;dubbo-async-processer&lt;/artifactId&gt;
+    &lt;version&gt;1.0.0-SNAPSHOT&lt;/version&gt;
+&lt;/dependency&gt;
+&lt;plugin&gt;
+    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
+    &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
+    &lt;version&gt;3.7.0&lt;/version&gt;
+    &lt;configuration&gt;
+        &lt;source&gt;1.8&lt;/source&gt;
+        &lt;target&gt;1.8&lt;/target&gt;
+        &lt;annotationProcessorPaths&gt;
+            &lt;path&gt;
+                &lt;groupId&gt;com.alibaba&lt;/groupId&gt;
+                &lt;artifactId&gt;dubbo-async-processer&lt;/artifactId&gt;
+                &lt;version&gt;1.0.0-SNAPSHOT&lt;/version&gt;
+            &lt;/path&gt;
+        &lt;/annotationProcessorPaths&gt;
+    &lt;/configuration&gt;
+&lt;/plugin&gt;
+</code></pre>
+<p>The above config is the Maven dependency that imports dubbo-async-processer 
processor. Developers who define interfaces (providing APIs) usually add the 
above dependencies to the project, so that when doing API packaging, the 
following interface definitions will be automatically generated in APIs:</p>
+<pre><code>/**
+* Generated by dubbo-async-processer
+*/
+package com.alibaba.dubbo.samples.api;
+import java.util.concurrent.CompletableFuture;
+@javax.annotation.Generated(&quot;com.alibaba.dubbo.async.processor.AsyncAnnotationProcessor&quot;)
+@org.apache.dubbo.common.config.AsyncFor(com.alibaba.dubbo.samples.api.GreetingsService.class)
+public interface GreetingsServiceAsync extends GreetingsService {
+CompletableFuture&lt;java.lang.String&gt; sayHiAsync(java.lang.String name);
+}
+</code></pre>
+</li>
+<li>
+<p>Provider side</p>
+<ul>
+<li>Config</li>
+</ul>
+<pre><code>&lt;bean id=&quot;greetingsService&quot; 
class=&quot;com.alibaba.dubbo.samples.async.impl.GreetingsServiceImpl&quot;/&gt;
+&lt;dubbo:service 
interface=&quot;com.alibaba.dubbo.samples.api.GreetingsService&quot; 
ref=&quot;greetingsService&quot;/&gt;
+</code></pre>
+<ul>
+<li>Service implementation</li>
+</ul>
+<pre><code>public class GreetingsServiceImpl implements GreetingsService {
+    @Override
+    public String sayHi(String name) {
+        return &quot;hi, &quot; + name;
+    }
+}
+</code></pre>
+</li>
+<li>
+<p>Consumer side</p>
+<ul>
+<li>Config</li>
+</ul>
+<pre><code> &lt;dubbo:reference id=&quot;greetingsService&quot; 
interface=&quot;com.alibaba.dubbo.samples.api.GreetingsServiceAsync&quot;/&gt;
+</code></pre>
+<p>Note that the service interface uses 
<strong>GreetingsServiceAsync</strong></p>
+<ul>
+<li>Service call</li>
+</ul>
+<pre><code> public static void main(String[] args) throws Exception {
+        ClassPathXmlApplicationContext context = new 
ClassPathXmlApplicationContext(new 
String[]{&quot;META-INF/spring/async-consumer.xml&quot;});
+        context.start();
+
+        GreetingsServiceAsync greetingsService = (GreetingsServiceAsync) 
context.getBean(&quot;greetingsService&quot;);
+        CompletableFuture&lt;String&gt; future = 
greetingsService.sayHiAsync(&quot;async call reqeust&quot;);
+        System.out.println(&quot;async call ret :&quot; + future.get());
+     
+        System.in.read();
+    }
+</code></pre>
+<p>In this way, we can use <code>CompletableFuture&lt;String&gt; future = 
greetingsService.sayHiAsync(&quot;async call reqeust&quot;);</code> 
directly,and return CompletableFuture.</p>
+</li>
+</ol>
+<h2>Example 3:Use AsyncContext</h2>
+<p>This example demonstrates how to implement the Provider-side asynchronous 
execution through AsyncContext based on the original synchronous interface. 
Code link <a 
href="https://github.com/dubbo/dubbo-samples/tree/samples-for-2.7.0-SNAPSHOT/dubbo-samples-async-provider";>dubbo-samples-async-provider</a>.</p>
+<ol>
+<li>
+<p>Interface definition</p>
+<pre><code>public interface AsyncService {
+    String sayHello(String name);
+}
+</code></pre>
+</li>
+<li>
+<p>Provider side</p>
+<ul>
+<li>Config</li>
+</ul>
+<pre><code>&lt;bean id=&quot;asyncService&quot; 
class=&quot;com.alibaba.dubbo.samples.async.impl.AsyncServiceImpl&quot;/&gt;
+&lt;dubbo:service async=&quot;true&quot; 
interface=&quot;com.alibaba.dubbo.samples.async.api.AsyncService&quot; 
ref=&quot;asyncService&quot;/&gt;
+</code></pre>
+<p>Note that adding <code>async=&quot;true&quot;</code> indicates that this is 
a service that starts the Provider-side execution asynchronously.</p>
+<ul>
+<li>Asynchronous execution implementation</li>
+</ul>
+<pre><code>public class AsyncServiceImpl implements AsyncService {
+    public String sayHello(String name) {
+        final AsyncContext asyncContext = RpcContext.startAsync();
+        new Thread(() -&gt; {
+            asyncContext.signalContextSwitch();
+            try {
+                Thread.sleep(500);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            asyncContext.write(&quot;Hello &quot; + name + &quot;, response 
from provider.&quot;);
+        }).start();
+        return null;
+    }
+}
+</code></pre>
+</li>
+<li>
+<p>Consumer side</p>
+<ul>
+<li>Config</li>
+</ul>
+<pre><code>&lt;dubbo:reference id=&quot;asyncService&quot; 
interface=&quot;com.alibaba.dubbo.samples.async.api.AsyncService&quot;/&gt;
+</code></pre>
+<ul>
+<li>Service call</li>
+</ul>
+<pre><code> public static void main(String[] args) throws Exception {
+        ClassPathXmlApplicationContext context = new 
ClassPathXmlApplicationContext(new 
String[]{&quot;META-INF/spring/async-consumer.xml&quot;});
+        context.start();
+
+        AsyncService asyncService = (AsyncService) 
context.getBean(&quot;asyncService&quot;);
+        System.out.println(asyncService.sayHello(&quot;async call 
request&quot;));
+     
+        System.in.read();
+    }
+</code></pre>
+</li>
+</ol>
+<h2>New problems resulted from asynchronization</h2>
+<h3>Filter Chain</h3>
+<p>The following is a complete Filter chain for a normal Dubbo call.</p>
+<p>After using the asynchronous call, since the asynchronous result is 
executed separately in the asynchronous thread, the Result passed through the 
second half of the Filter chain is null, and the real result cannot be 
processed by the Filter chain when it is returned.</p>
+<p>In order to solve this problem, PostProcessFilter and 
AbstractPostProcessFilter were introduced in Dubbo 2.7.0. The PostProcessFilter 
interface extends from the Filter interface, and AbstractPostProcessFilter is 
an abstract implementation of PostProcessFilter.</p>
+<p>The following is an example of extending the Filter and supporting the 
asynchronous Filter chain.</p>
+<pre><code>@Activate(group = {Constants.PROVIDER, Constants.CONSUMER})
+public class AsyncPostprocessFilter extends AbstractPostProcessFilter {
+
+    @Override
+    public Result invoke(Invoker&lt;?&gt; invoker, Invocation invocation) 
throws RpcException {
+        return postProcessResult(invoker.invoke(invocation), invoker, 
invocation);
+    }
+
+    @Override
+    protected Result doPostProcess(Result result, Invoker&lt;?&gt; invoker, 
Invocation invocation) {
+        System.out.println(&quot;Filter get the return value: &quot; + 
result.getValue());
+        return result;
+    }
+}
+</code></pre>
+<h3>Context passing</h3>
+<p>Currently, the context we are considering mainly refers to the data stored 
in the RpcContext. In most scenarios, the user needs to complete the passing of 
the Context before switching the service thread.</p>
+<pre><code>public class AsyncServiceImpl implements AsyncService {
+    // Save the context of the current thread
+    RpcContext context = RpcContext.getContext();
+    public CompletableFuture&lt;String&gt; sayHello(String name) {
+        return CompletableFuture.supplyAsync(() -&gt; {
+            // Set context into new thread
+            RpcContext.setContext(context);
+            try {
+                Thread.sleep(5000);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            return &quot;async response from provider.&quot;;
+        });
+    }
+}
+</code></pre>
+<p>However, AsyncContext also provides the signalContextSwitch() method for a 
convenient Context switch.</p>
+<pre><code>public class AsyncServiceImpl implements AsyncService {
+    public String sayHello(String name) {
+        final AsyncContext asyncContext = RpcContext.startAsync();
+        new Thread(() -&gt; {
+            asyncContext.signalContextSwitch();
+            try {
+                Thread.sleep(500);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            asyncContext.write(&quot;Hello &quot; + name + &quot;, response 
from provider.&quot;);
+        }).start();
+        return null;
+    }
+}
+</code></pre>
+</section><footer class="footer-container" data-reactid="19"><div 
class="footer-body" data-reactid="20"><img src="/img/dubbo_gray.png" 
data-reactid="21"/><img class="apache" src="/img/apache_logo.png" 
data-reactid="22"/><div class="cols-container" data-reactid="23"><div 
class="col col-12" data-reactid="24"><h3 data-reactid="25">Disclaimer</h3><p 
data-reactid="26">Apache Dubbo is an effort undergoing incubation at The Apache 
Software Foundation (ASF), sponsored by the Incubator. Incubatio [...]
+       <script 
src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js";></script>
+       <script 
src="https://f.alicdn.com/react/15.4.1/react-dom.min.js";></script>
+       <script>
+               window.rootPath = '';
+  </script>
+  <script src="/build/blogDetail.js"></script>
+  <!-- Global site tag (gtag.js) - Google Analytics -->
+       <script async 
src="https://www.googletagmanager.com/gtag/js?id=UA-112489517-1";></script>
+       <script>
+               window.dataLayer = window.dataLayer || [];
+               function gtag(){dataLayer.push(arguments);}
+               gtag('js', new Date());
+
+               gtag('config', 'UA-112489517-1');
+       </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/en-us/blog/dubbo-new-async.json b/en-us/blog/dubbo-new-async.json
new file mode 100644
index 0000000..afced92
--- /dev/null
+++ b/en-us/blog/dubbo-new-async.json
@@ -0,0 +1,4 @@
+{
+  "filename": "dubbo-new-async.md",
+  "__html": "<h1>How to implement a fully asynchronous calls chain based on 
Dubbo.</h1>\n<p>Implementing the full asynchronous programming based on Dubbo, 
which is a new feature introduced in version 2.7.0 after the enhancement of the 
existing asynchronous mode.This article first reviews the supported functions 
and existing problems of asynchronization in 2.6.x and earlier versions, and 
introduces the targeted enhancements based on CompletableFuture in version 
2.7.0. Then, the use of enh [...]
+}
\ No newline at end of file
diff --git a/en-us/blog/index.html b/en-us/blog/index.html
index e924faa..9f09dd1 100644
--- a/en-us/blog/index.html
+++ b/en-us/blog/index.html
@@ -12,7 +12,7 @@
        <link rel="stylesheet" href="/build/blog.css" />
 </head>
 <body>
-       <div id="root"><div class="blog-list-page" data-reactroot="" 
data-reactid="1" data-react-checksum="1283340498"><header 
class="header-container header-container-normal" data-reactid="2"><div 
class="header-body" data-reactid="3"><a href="/en-us/index.html" 
data-reactid="4"><img class="logo" src="/img/dubbo_colorful.png" 
data-reactid="5"/></a><span class="language-switch language-switch-normal" 
data-reactid="6">中</span><div class="header-menu" data-reactid="7"><img 
class="header-menu-toggl [...]
+       <div id="root"><div class="blog-list-page" data-reactroot="" 
data-reactid="1" data-react-checksum="1267967996"><header 
class="header-container header-container-normal" data-reactid="2"><div 
class="header-body" data-reactid="3"><a href="/en-us/index.html" 
data-reactid="4"><img class="logo" src="/img/dubbo_colorful.png" 
data-reactid="5"/></a><span class="language-switch language-switch-normal" 
data-reactid="6">中</span><div class="header-menu" data-reactid="7"><img 
class="header-menu-toggl [...]
        <script 
src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js";></script>
        <script 
src="https://f.alicdn.com/react/15.4.1/react-dom.min.js";></script>
        <script>
diff --git a/en-us/blog/introduction-to-dubbo-spi-2.html 
b/en-us/blog/introduction-to-dubbo-spi-2.html
new file mode 100644
index 0000000..f52e125
--- /dev/null
+++ b/en-us/blog/introduction-to-dubbo-spi-2.html
@@ -0,0 +1,388 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+       <meta charset="UTF-8">
+       <meta name="viewport" content="width=device-width, initial-scale=1.0, 
maximum-scale=1.0, user-scalable=no">
+       <meta name="keywords" content="introduction-to-dubbo-spi-2" />
+       <meta name="description" content="introduction-to-dubbo-spi-2" />
+       <!-- 网页标签标题 -->
+       <title>introduction-to-dubbo-spi-2</title>
+       <link rel="shortcut icon" href="/img/dubbo.ico"/>
+       <link rel="stylesheet" href="/build/blogDetail.css" />
+</head>
+<body>
+       <div id="root"><div class="blog-detail-page" data-reactroot="" 
data-reactid="1" data-react-checksum="1212085058"><header 
class="header-container header-container-normal" data-reactid="2"><div 
class="header-body" data-reactid="3"><a href="/en-us/index.html" 
data-reactid="4"><img class="logo" src="/img/dubbo_colorful.png" 
data-reactid="5"/></a><span class="language-switch language-switch-normal" 
data-reactid="6">中</span><div class="header-menu" data-reactid="7"><img 
class="header-menu-tog [...]
+<hr>
+<p>In the <a href="#/blog/introduction-to-dubbo-spi.md">actual implementation 
of the Dubbo extensibility mechanism</a>, we learned some concepts of the Dubbo 
extension mechanism, explored the implementation of LoadBalance in Dubbo, and 
implemented a LoadBalance on our own. Do you think Dubbo's extension mechanism 
is great? Next, we will go deep into the source code of Dubbo and see what it 
is.</p>
+<h1>ExtensionLoader</h1>
+<p>ExtentionLoader is the core class, which is responsible for the loading and 
lifecycle management of extension points. Let's start with this class. There 
are many methods of Extension, and the common methods include:</p>
+<ul>
+<li><code>public static &lt;T&gt; ExtensionLoader&lt;T&gt; 
getExtensionLoader(Class&lt;T&gt; type)</code></li>
+<li><code>public T getExtension(String name)</code></li>
+<li><code>public T getAdaptiveExtension()</code></li>
+</ul>
+<p>The common usages are:</p>
+<ul>
+<li><code>LoadBalance lb = 
ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(loadbalanceName)</code></li>
+<li><code>RouterFactory routerFactory = 
ExtensionLoader.getExtensionLoader(RouterFactory.class).getAdaptiveExtension()</code></li>
+</ul>
+<p>Notice: In the source code shown below, I'll remove extraneous code (such 
as logging, exception catching, and so on) to make it easy to read and 
understand.</p>
+<ol>
+<li>getExtensionLoader
+This is a static factory method that enters an extensible interface and 
returns an ExtensionLoader entity class for this interface. With this entity 
class, you can get not only a specific extension based on name, but also an 
adaptive extension.</li>
+</ol>
+<pre><code class="language-java"><span class="hljs-keyword">public</span> 
<span class="hljs-keyword">static</span> &lt;T&gt; <span 
class="hljs-function">ExtensionLoader&lt;T&gt; <span 
class="hljs-title">getExtensionLoader</span><span 
class="hljs-params">(Class&lt;T&gt; type)</span> </span>{
+        <span class="hljs-comment">// An extension point must be an 
interface</span>
+        <span class="hljs-keyword">if</span> (!type.isInterface()) {
+            <span class="hljs-keyword">throw</span> <span 
class="hljs-keyword">new</span> IllegalArgumentException(<span 
class="hljs-string">"Extension type("</span> + type + <span 
class="hljs-string">") is not interface!"</span>);
+        }
+        <span class="hljs-comment">// @SPI annotations must be provided</span>
+        <span class="hljs-keyword">if</span> (!withExtensionAnnotation(type)) {
+            <span class="hljs-keyword">throw</span> <span 
class="hljs-keyword">new</span> IllegalArgumentException(<span 
class="hljs-string">"Extension type without @SPI Annotation!"</span>);
+        }
+        <span class="hljs-comment">// Get the corresponding ExtensionLoader 
from the cache according to the interface</span>
+        <span class="hljs-comment">// Each extension will only be loaded 
once</span>
+        ExtensionLoader&lt;T&gt; loader = (ExtensionLoader&lt;T&gt;) 
EXTENSION_LOADERS.get(type);
+        <span class="hljs-keyword">if</span> (loader == <span 
class="hljs-keyword">null</span>) {
+            <span class="hljs-comment">// Initialize extension</span>
+            EXTENSION_LOADERS.putIfAbsent(type, <span 
class="hljs-keyword">new</span> ExtensionLoader&lt;T&gt;(type));
+            loader = (ExtensionLoader&lt;T&gt;) EXTENSION_LOADERS.get(type);
+        }
+        <span class="hljs-keyword">return</span> loader;
+    }
+    
+<span class="hljs-function"><span class="hljs-keyword">private</span> <span 
class="hljs-title">ExtensionLoader</span><span 
class="hljs-params">(Class&lt;?&gt; type)</span> </span>{
+        <span class="hljs-keyword">this</span>.type = type;
+        objectFactory = (type == ExtensionFactory.class ? <span 
class="hljs-keyword">null</span> : 
ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
+    }
+</code></pre>
+<ol start="2">
+<li>getExtension</li>
+</ol>
+<pre><code class="language-java"><span class="hljs-function"><span 
class="hljs-keyword">public</span> T <span 
class="hljs-title">getExtension</span><span class="hljs-params">(String 
name)</span> </span>{
+        Holder&lt;Object&gt; holder = cachedInstances.get(name);
+        <span class="hljs-keyword">if</span> (holder == <span 
class="hljs-keyword">null</span>) {
+            cachedInstances.putIfAbsent(name, <span 
class="hljs-keyword">new</span> Holder&lt;Object&gt;());
+            holder = cachedInstances.get(name);
+        }
+        Object instance = holder.get();
+        <span class="hljs-comment">// Get it from the cache. If it does not 
exist, create</span>
+        <span class="hljs-keyword">if</span> (instance == <span 
class="hljs-keyword">null</span>) {
+            <span class="hljs-keyword">synchronized</span> (holder) {
+                instance = holder.get();
+                <span class="hljs-keyword">if</span> (instance == <span 
class="hljs-keyword">null</span>) {
+                    instance = createExtension(name);
+                    holder.set(instance);
+                }
+            }
+        }
+        <span class="hljs-keyword">return</span> (T) instance;
+    }
+</code></pre>
+<p>Some judgments and caching have been made in the getExtention method, and 
the main logic is in the createExtension method. Let's move on to the 
createExtention method.</p>
+<pre><code class="language-java"><span class="hljs-function"><span 
class="hljs-keyword">private</span> T <span 
class="hljs-title">createExtension</span><span class="hljs-params">(String 
name)</span> </span>{
+        <span class="hljs-comment">// Get the extension class according to the 
name of extension point. For example,  for LoadBalance, get the 
RandomLoadBalance class according to random</span>
+        Class&lt;?&gt; clazz = getExtensionClasses().get(name);
+        
+        T instance = (T) EXTENSION_INSTANCES.get(clazz);
+        <span class="hljs-keyword">if</span> (instance == <span 
class="hljs-keyword">null</span>) {
+              <span class="hljs-comment">// Use reflection to call newInstance 
to create an example of an extension class</span>
+            EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
+            instance = (T) EXTENSION_INSTANCES.get(clazz);
+        }
+        <span class="hljs-comment">// Make dependency injection for the 
extended class samples</span>
+        injectExtension(instance);
+        <span class="hljs-comment">// If there is a wrapper, add the 
wrapper</span>
+        Set&lt;Class&lt;?&gt;&gt; wrapperClasses = cachedWrapperClasses;
+        <span class="hljs-keyword">if</span> (wrapperClasses != <span 
class="hljs-keyword">null</span> &amp;&amp; !wrapperClasses.isEmpty()) {
+            <span class="hljs-keyword">for</span> (Class&lt;?&gt; wrapperClass 
: wrapperClasses) {
+                instance = injectExtension((T) 
wrapperClass.getConstructor(type).newInstance(instance));
+            }
+        }
+        <span class="hljs-keyword">return</span> instance;
+}
+</code></pre>
+<p>The createExtension method has done the following:</p>
+<ol>
+<li>First, get the corresponding extension class according to name. Read the 
extension point configuration file from the <code>META-INF</code> folder under 
ClassPath.</li>
+<li>Use reflection to create an instance of an extended class.</li>
+<li>make dependency injection for the attributes of the extended class 
instance. That is, IoC.</li>
+<li>If there is a wrapper, add the wrapper. That is, AoP.</li>
+</ol>
+<p>Let's focus on these four processes.</p>
+<ol>
+<li>Get the corresponding extension class according to name. Let’s read the 
code first:</li>
+</ol>
+<pre><code class="language-java"><span class="hljs-keyword">private</span> 
Map&lt;String, Class&lt;?&gt;&gt; getExtensionClasses() {
+        Map&lt;String, Class&lt;?&gt;&gt; classes = cachedClasses.get();
+        <span class="hljs-keyword">if</span> (classes == <span 
class="hljs-keyword">null</span>) {
+            <span class="hljs-keyword">synchronized</span> (cachedClasses) {
+                classes = cachedClasses.get();
+                <span class="hljs-keyword">if</span> (classes == <span 
class="hljs-keyword">null</span>) {
+                    classes = loadExtensionClasses();
+                    cachedClasses.set(classes);
+                }
+            }
+        }
+        <span class="hljs-keyword">return</span> classes;
+    }
+
+    <span class="hljs-comment">// synchronized in getExtensionClasses</span>
+    <span class="hljs-keyword">private</span> Map&lt;String, 
Class&lt;?&gt;&gt; loadExtensionClasses() {
+        <span class="hljs-keyword">final</span> SPI defaultAnnotation = 
type.getAnnotation(SPI.class);
+        <span class="hljs-keyword">if</span> (defaultAnnotation != <span 
class="hljs-keyword">null</span>) {
+            String value = defaultAnnotation.value();
+            <span class="hljs-keyword">if</span> (value != <span 
class="hljs-keyword">null</span> &amp;&amp; (value = value.trim()).length() 
&gt; <span class="hljs-number">0</span>) {
+                String[] names = NAME_SEPARATOR.split(value);
+                <span class="hljs-keyword">if</span> (names.length &gt; <span 
class="hljs-number">1</span>) {
+                    <span class="hljs-keyword">throw</span> <span 
class="hljs-keyword">new</span> IllegalStateException(<span 
class="hljs-string">"more than 1 default extension name on extension "</span> + 
type.getName());
+                }
+                <span class="hljs-keyword">if</span> (names.length == <span 
class="hljs-number">1</span>) cachedDefaultName = names[<span 
class="hljs-number">0</span>];
+            }
+        }
+
+        Map&lt;String, Class&lt;?&gt;&gt; extensionClasses = <span 
class="hljs-keyword">new</span> HashMap&lt;String, Class&lt;?&gt;&gt;();
+        loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
+        loadFile(extensionClasses, DUBBO_DIRECTORY);
+        loadFile(extensionClasses, SERVICES_DIRECTORY);
+        <span class="hljs-keyword">return</span> extensionClasses;
+    }
+</code></pre>
+<p>This process is very simple. Get the extension class from the cache first, 
and if it does not exist, load it from the configuration file. The path of the 
configuration file has been mentioned before:</p>
+<ul>
+<li><code>META-INF/dubbo/internal</code></li>
+<li><code>META-INF/dubbo</code></li>
+<li><code>META-INF/services</code></li>
+</ul>
+<ol start="2">
+<li>Use reflection to create an extended instance. This process is very 
simple. We can do this using <code>clazz.newInstance()</code>. The attributes 
of the extended instance created are all null values.</li>
+<li>Extended instance is automatic assembly. In the actual scenario, there 
have dependencies between classes. Dependencies are also referenced in the 
extended instance, such as a simple Java class, an extension of another Dubbo, 
or a Spring Bean. The situation of dependencies is complex, and Dubbo's 
processing is relatively complicated. We will have a special chapter to explain 
it later. Now, we just need to know that Dubbo can correctly inject common 
dependencies in extension points, Du [...]
+<li>Extended instance is auto-wrapping. Auto-wrapping is about implementing 
Spring like AOP functionality. Dubbo uses it to implement some common functions 
internally, such as logging, monitoring, and so on. The contents of the 
extended instance auto-wrapper will also be explained separately later.</li>
+</ol>
+<p>After the above 4 steps, Dubbo creates and initializes an extended 
instance. The dependencies of this instance are injected and packaged as 
needed. At this point, this extended instance can be used.</p>
+<h1>Auto-assembly of Dubbo SPI advanced usage</h1>
+<p>The relevant code for auto-assembly is in the injectExtension method:</p>
+<pre><code class="language-java"><span class="hljs-function"><span 
class="hljs-keyword">private</span> T <span 
class="hljs-title">injectExtension</span><span class="hljs-params">(T 
instance)</span> </span>{
+    <span class="hljs-keyword">for</span> (Method method : 
instance.getClass().getMethods()) {
+        <span class="hljs-keyword">if</span> 
(method.getName().startsWith(<span class="hljs-string">"set"</span>)
+                &amp;&amp; method.getParameterTypes().length == <span 
class="hljs-number">1</span>
+                &amp;&amp; Modifier.isPublic(method.getModifiers())) {
+            Class&lt;?&gt; pt = method.getParameterTypes()[<span 
class="hljs-number">0</span>];
+          
+            String property = method.getName().length() &gt; <span 
class="hljs-number">3</span> ? method.getName().substring(<span 
class="hljs-number">3</span>, <span class="hljs-number">4</span>).toLowerCase() 
+ method.getName().substring(<span class="hljs-number">4</span>) : <span 
class="hljs-string">""</span>;
+            Object object = objectFactory.getExtension(pt, property);
+            <span class="hljs-keyword">if</span> (object != <span 
class="hljs-keyword">null</span>) {
+                method.invoke(instance, object);
+            }
+        }
+    }
+    <span class="hljs-keyword">return</span> instance;
+}
+</code></pre>
+<p>To accomplish the automatic assembly of dependencies of the extended 
instances, you first need to know what the dependencies are and what the types 
of dependencies are. The solution of Dubbo is to find the Java standard setter 
method. That is, the method name starting with set has only one parameter. If 
such a set method exists in an extension class, Dubbo injects it into 
dependencies, which is similar to the injection of Spring's set method. 
However, dependency injection in Dubbo is  [...]
+<pre><code class="language-java"><span class="hljs-function"><span 
class="hljs-keyword">private</span> <span 
class="hljs-title">ExtensionLoader</span><span 
class="hljs-params">(Class&lt;?&gt; type)</span> </span>{
+        <span class="hljs-keyword">this</span>.type = type;
+        objectFactory = (type == ExtensionFactory.class ? <span 
class="hljs-keyword">null</span> : 
ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
+    }
+</code></pre>
+<p>ObjectFacore is also an extension, obtained through 
<code>ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()</code>.</p>
+<p><img 
src="https://raw.githubusercontent.com/vangoleo/wiki/master/dubbo/dubbo-extensionfactory.png";
 alt="Dubbo-ExtensionFactory | left"></p>
+<p>ExtensionLoader includes three implementations:</p>
+<ol>
+<li>SpiExtensionLoader: use Dubbo's Spi to load Extension.</li>
+<li>SpringExtensionLoader: load Extension from the Spring container.</li>
+<li>AdaptiveExtensionLoader: adaptive AdaptiveExtensionLoader</li>
+</ol>
+<p>Pay attention to the AdaptiveExtensionLoader here, the source code is as 
follows:</p>
+<pre><code class="language-java"><span class="hljs-meta">@Adaptive</span>
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span 
class="hljs-keyword">class</span> <span 
class="hljs-title">AdaptiveExtensionFactory</span> <span 
class="hljs-keyword">implements</span> <span 
class="hljs-title">ExtensionFactory</span> </span>{
+
+    <span class="hljs-keyword">private</span> <span 
class="hljs-keyword">final</span> List&lt;ExtensionFactory&gt; factories;
+
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span 
class="hljs-title">AdaptiveExtensionFactory</span><span 
class="hljs-params">()</span> </span>{
+        ExtensionLoader&lt;ExtensionFactory&gt; loader = 
ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
+        List&lt;ExtensionFactory&gt; list = <span 
class="hljs-keyword">new</span> ArrayList&lt;ExtensionFactory&gt;();
+        <span class="hljs-keyword">for</span> (String name : 
loader.getSupportedExtensions()) {
+            list.add(loader.getExtension(name));
+        }
+        factories = Collections.unmodifiableList(list);
+    }
+
+    <span class="hljs-keyword">public</span> &lt;T&gt; <span 
class="hljs-function">T <span class="hljs-title">getExtension</span><span 
class="hljs-params">(Class&lt;T&gt; type, String name)</span> </span>{
+        <span class="hljs-keyword">for</span> (ExtensionFactory factory : 
factories) {
+            T extension = factory.getExtension(type, name);
+            <span class="hljs-keyword">if</span> (extension != <span 
class="hljs-keyword">null</span>) {
+                <span class="hljs-keyword">return</span> extension;
+            }
+        }
+        <span class="hljs-keyword">return</span> <span 
class="hljs-keyword">null</span>;
+    }
+}
+</code></pre>
+<p>The AdaptiveExtensionLoader class has @Adaptive annotations. As mentioned 
earlier, Dubbo creates an adaptive instance for each extension. If the 
extension class has @Adaptive annotations, it will use it as an adaptive class. 
If not, Dubbo will create one for us. So 
<code>ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension())</code>
 will return an AdaptiveExtensionLoader instance as an adaptive extension 
instance.
+The AdaptiveExtentionLoader will iterate through all the ExtensionFactory 
implementations and try to load the extensions. If found, return. If not, 
continue to find it in the next ExtensionFactory. Dubbo has two 
ExtensionFactory built in, which are searched from Dubbo's own extension 
mechanism and Spring container. Since ExtensionFactory itself is also an 
extension point, we can implement our own ExtensionFactory to enable automatic 
assembly of Dubbo to support our custom components. For [...]
+<h1>AoP of Dubbo SPI advanced usage</h1>
+<p>We often use AOP functionality when using Spring. Insert other logic before 
and after the method of the target class. For example, Spring AOP is usually 
used to implement logging, monitoring, and authentication, and so on.
+Does Dubbo's extension mechanism also support similar features? The answer is 
yes. In Dubbo, there is a special class called the Wrapper class. It uses the 
wrapper class to wrap the original extension point instance through the 
decorator pattern, and then inserts additional logic before and after the 
original extension point implementation to implement AOP functionality.</p>
+<h3>What is the Wrapper class</h3>
+<p>So what kind of class is the Wrapper class in the Dubbo extension 
mechanism? The Wrapper class is a class that has a replication constructor and 
also is a typical decorator pattern. Here's a Wrapper class:</p>
+<pre><code class="language-java"><span class="hljs-class"><span 
class="hljs-keyword">class</span> <span class="hljs-title">A</span></span>{
+    <span class="hljs-keyword">private</span> A a;
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span 
class="hljs-title">A</span><span class="hljs-params">(A a)</span></span>{
+        <span class="hljs-keyword">this</span>.a = a;
+    }
+}
+</code></pre>
+<p>Class A has a constructor <code>public A(A a)</code>, and the argument to 
the constructor is A itself. Such a class can be a Wrapper class in the Dubbo 
extension mechanism. Such Wrapper classes in Dubbo include 
ProtocolFilterWrapper, ProtocolListenerWrapper, and so on. You can check the 
source code to deepen your understanding.</p>
+<h3>How to configure the Wrapper class</h3>
+<p>The Wipper class in Dubbo is also an extension point. Like other extension 
points, it is also configured in the <code>META-INF</code> folder. For example, 
the ProtocolFilterWrapper and ProtocolListenerWrapper in the previous example 
are configured in the path 
<code>dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol</code>:</p>
+<pre><code 
class="language-text">filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper
+listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper
+mock=com.alibaba.dubbo.rpc.support.MockProtocol
+</code></pre>
+<p>When Dubbo loads the extension configuration file, there is a piece of code 
as follows:</p>
+<pre><code class="language-java"><span class="hljs-keyword">try</span> {  
+  clazz.getConstructor(type);    
+  Set&lt;Class&lt;?&gt;&gt; wrappers = cachedWrapperClasses;
+  <span class="hljs-keyword">if</span> (wrappers == <span 
class="hljs-keyword">null</span>) {
+    cachedWrapperClasses = <span class="hljs-keyword">new</span> 
ConcurrentHashSet&lt;Class&lt;?&gt;&gt;();
+    wrappers = cachedWrapperClasses;
+  }
+  wrappers.add(clazz);
+} <span class="hljs-keyword">catch</span> (NoSuchMethodException e) {}
+</code></pre>
+<p>The meaning of this code is that if the extension class has a copy 
constructor, it will be saved for later use. The class that has the copy 
constructor is the Wrapper class. The parameter obtained by 
<code>clazz.getConstructor(type)</code> is the constructor of the extension 
point interface. Note that the parameter type of the constructor is an 
extension point interface, not an extension class.
+Take Protocol as an example. The configuration file 
<code>dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol
 defines filter=com.alibaba.dubbo.rpc.protocol. ProtocolFilterWrapper</code>.
+The code of ProtocolFilterWrapper is as follows:</p>
+<pre><code class="language-java"><span class="hljs-keyword">public</span> 
<span class="hljs-class"><span class="hljs-keyword">class</span> <span 
class="hljs-title">ProtocolFilterWrapper</span> <span 
class="hljs-keyword">implements</span> <span class="hljs-title">Protocol</span> 
</span>{
+
+    <span class="hljs-keyword">private</span> <span 
class="hljs-keyword">final</span> Protocol protocol;
+
+    <span class="hljs-comment">// One parameter is the copy constructor of 
Protocol</span>
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span 
class="hljs-title">ProtocolFilterWrapper</span><span 
class="hljs-params">(Protocol protocol)</span> </span>{
+        <span class="hljs-keyword">if</span> (protocol == <span 
class="hljs-keyword">null</span>) {
+            <span class="hljs-keyword">throw</span> <span 
class="hljs-keyword">new</span> IllegalArgumentException(<span 
class="hljs-string">"protocol == null"</span>);
+        }
+        <span class="hljs-keyword">this</span>.protocol = protocol;
+    }
+</code></pre>
+<p>ProtocolFilterWrapper has a constructor <code>public 
ProtocolFilterWrapper(Protocol protocol)</code>, and the parameter is the 
extension point Protocol. So it is a Wrapper class in the Dubbo extension 
mechanism. The ExtensionLoader will cache it. When creating Extension instances 
later, the ExtensionLoader use these wrapper classes to wrap the original 
Extension point in turn.</p>
+<h1>Extension point adaptive</h1>
+<p>As mentioned earlier, Dubbo needs to determine which extension to use based 
on method parameters at runtime. So there is an extension point adaptive 
instance. In fact, it is an extension point proxy that delays the selection of 
extensions from starting Dubbo to calling RPC. Each extension point in Dubbo 
has an adaptive class. If it is not explicitly provided, Dubbo will 
automatically create one for us. By default, Javaassist is used.
+Let's first look at the code to create an adaptive extension class:</p>
+<pre><code class="language-java"><span class="hljs-function"><span 
class="hljs-keyword">public</span> T <span 
class="hljs-title">getAdaptiveExtension</span><span 
class="hljs-params">()</span> </span>{
+    Object instance = cachedAdaptiveInstance.get();
+    <span class="hljs-keyword">if</span> (instance == <span 
class="hljs-keyword">null</span>) {
+            <span class="hljs-keyword">synchronized</span> 
(cachedAdaptiveInstance) {
+                instance = cachedAdaptiveInstance.get();
+                <span class="hljs-keyword">if</span> (instance == <span 
class="hljs-keyword">null</span>) {
+                      instance = createAdaptiveExtension();
+                      cachedAdaptiveInstance.set(instance); 
+                }
+            }        
+    }
+
+    <span class="hljs-keyword">return</span> (T) instance;
+}
+</code></pre>
+<p>Continue to read the createAdaptiveExtension method:</p>
+<pre><code class="language-java"><span class="hljs-function"><span 
class="hljs-keyword">private</span> T <span 
class="hljs-title">createAdaptiveExtension</span><span 
class="hljs-params">()</span> </span>{        
+    <span class="hljs-keyword">return</span> injectExtension((T) 
getAdaptiveExtensionClass().newInstance());
+}
+</code></pre>
+<p>Continue to read the getAdaptiveExtensionClass method:</p>
+<pre><code class="language-java"><span class="hljs-keyword">private</span> 
Class&lt;?&gt; getAdaptiveExtensionClass() {
+        getExtensionClasses();
+        <span class="hljs-keyword">if</span> (cachedAdaptiveClass != <span 
class="hljs-keyword">null</span>) {
+            <span class="hljs-keyword">return</span> cachedAdaptiveClass;
+        }
+        <span class="hljs-keyword">return</span> cachedAdaptiveClass = 
createAdaptiveExtensionClass();
+    }
+</code></pre>
+<p>Continue to read the createAdaptiveExtensionClass method. After a long 
journey, we finally come to a concrete realization. Look at this 
createAdaptiveExtensionClass method, which first generates the Java source code 
for the adaptive class, and then compile the source code into Java bytecode and 
load it into the JVM.</p>
+<pre><code class="language-java"><span class="hljs-keyword">private</span> 
Class&lt;?&gt; createAdaptiveExtensionClass() {
+        String code = createAdaptiveExtensionClassCode();
+        ClassLoader classLoader = findClassLoader();
+        com.alibaba.dubbo.common.compiler.Compiler compiler = 
ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
+        <span class="hljs-keyword">return</span> compiler.compile(code, 
classLoader);
+    }
+</code></pre>
+<p>The default implementation of Compiler's code is javassist.</p>
+<pre><code class="language-java"><span class="hljs-meta">@SPI</span>(<span 
class="hljs-string">"javassist"</span>)
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span 
class="hljs-keyword">interface</span> <span class="hljs-title">Compiler</span> 
</span>{
+    Class&lt;?&gt; compile(String code, ClassLoader classLoader);
+}
+</code></pre>
+<p>The createAdaptiveExtensionClassCode () method uses a StringBuilder to 
build Java source code for the adaptive class. The method implementation is 
relatively long, and the code is not posted here. The approach to bytecode 
generation is also interesting, first generating Java source code, then 
compiling it and loading it into the jvm. In this way, the generated Java class 
can be better controlled. And it doesn't have to care about the API of the 
bytecode generation framework. Because t [...]
+Below are the Java code example for Protocol adaptive class created by 
createAdaptiveExtensionClassCode method:</p>
+<pre><code class="language-java"><span class="hljs-keyword">package</span> 
com.alibaba.dubbo.rpc;
+
+<span class="hljs-keyword">import</span> 
com.alibaba.dubbo.common.extension.ExtensionLoader;
+
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span 
class="hljs-keyword">class</span> <span 
class="hljs-title">Protocol</span>$<span class="hljs-title">Adpative</span> 
<span class="hljs-keyword">implements</span> <span 
class="hljs-title">com</span>.<span class="hljs-title">alibaba</span>.<span 
class="hljs-title">dubbo</span>.<span class="hljs-title">rpc</span>.<span 
class="hljs-title">Protocol</span> </span>{
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span 
class="hljs-keyword">void</span> <span class="hljs-title">destroy</span><span 
class="hljs-params">()</span> </span>{
+        <span class="hljs-keyword">throw</span> <span 
class="hljs-keyword">new</span> UnsupportedOperationException(<span 
class="hljs-string">"method public abstract void 
com.alibaba.dubbo.rpc.Protocol.destroy() of interface 
com.alibaba.dubbo.rpc.Protocol is not adaptive method!"</span>);
+    }
+
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span 
class="hljs-keyword">int</span> <span 
class="hljs-title">getDefaultPort</span><span class="hljs-params">()</span> 
</span>{
+        <span class="hljs-keyword">throw</span> <span 
class="hljs-keyword">new</span> UnsupportedOperationException(<span 
class="hljs-string">"method public abstract int 
com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface 
com.alibaba.dubbo.rpc.Protocol is not adaptive method!"</span>);
+    }
+
+    <span class="hljs-keyword">public</span> com.alibaba.dubbo.rpc.<span 
class="hljs-function">Exporter <span class="hljs-title">export</span><span 
class="hljs-params">(com.alibaba.dubbo.rpc.Invoker arg0)</span> <span 
class="hljs-keyword">throws</span> com.alibaba.dubbo.rpc.RpcException </span>{
+        <span class="hljs-keyword">if</span> (arg0 == <span 
class="hljs-keyword">null</span>) <span class="hljs-keyword">throw</span> <span 
class="hljs-keyword">new</span> IllegalArgumentException(<span 
class="hljs-string">"com.alibaba.dubbo.rpc.Invoker argument == null"</span>);
+        <span class="hljs-keyword">if</span> (arg0.getUrl() == <span 
class="hljs-keyword">null</span>)
+            <span class="hljs-keyword">throw</span> <span 
class="hljs-keyword">new</span> IllegalArgumentException(<span 
class="hljs-string">"com.alibaba.dubbo.rpc.Invoker argument getUrl() == 
null"</span>);
+        com.alibaba.dubbo.common.URL url = arg0.getUrl();
+        String extName = (url.getProtocol() == <span 
class="hljs-keyword">null</span> ? <span class="hljs-string">"dubbo"</span> : 
url.getProtocol());
+        <span class="hljs-keyword">if</span> (extName == <span 
class="hljs-keyword">null</span>)
+            <span class="hljs-keyword">throw</span> <span 
class="hljs-keyword">new</span> IllegalStateException(<span 
class="hljs-string">"Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name 
from url("</span> + url.toString() + <span class="hljs-string">") use 
keys([protocol])"</span>);
+        com.alibaba.dubbo.rpc.Protocol extension = 
(com.alibaba.dubbo.rpc.Protocol) 
ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
+        <span class="hljs-keyword">return</span> extension.export(arg0);
+    }
+
+    <span class="hljs-keyword">public</span> com.alibaba.dubbo.rpc.<span 
class="hljs-function">Invoker <span class="hljs-title">refer</span><span 
class="hljs-params">(java.lang.Class arg0, com.alibaba.dubbo.common.URL 
arg1)</span> <span class="hljs-keyword">throws</span> 
com.alibaba.dubbo.rpc.RpcException </span>{
+        <span class="hljs-keyword">if</span> (arg1 == <span 
class="hljs-keyword">null</span>) <span class="hljs-keyword">throw</span> <span 
class="hljs-keyword">new</span> IllegalArgumentException(<span 
class="hljs-string">"url == null"</span>);
+        com.alibaba.dubbo.common.URL url = arg1;
+        String extName = (url.getProtocol() == <span 
class="hljs-keyword">null</span> ? <span class="hljs-string">"dubbo"</span> : 
url.getProtocol());
+        <span class="hljs-keyword">if</span> (extName == <span 
class="hljs-keyword">null</span>)
+            <span class="hljs-keyword">throw</span> <span 
class="hljs-keyword">new</span> IllegalStateException(<span 
class="hljs-string">"Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name 
from url("</span> + url.toString() + <span class="hljs-string">") use 
keys([protocol])"</span>);
+        com.alibaba.dubbo.rpc.Protocol extension = 
(com.alibaba.dubbo.rpc.Protocol) 
ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
+        <span class="hljs-keyword">return</span> extension.refer(arg0, arg1);
+    }
+}
+</code></pre>
+<p>The general logic is the same as at the beginning. The parameters are 
parsed through the url, and the parsed logic is controlled by the value 
parameter of @adaptive, and then the extension points implementation are 
obtained according to the name of the extension point. And then finally make 
the call. If you want to know the specific construction logic of .Java code, 
you can see the complete implementation of 
<code>createAdaptiveExtensionClassCode</code>.
+In the generated Protocol$Adpative, both the getDefaultPort and destroy 
methods are found to throw the exception directly. Why? Take a look at the 
source code of Protocol:</p>
+<pre><code class="language-java"><span class="hljs-meta">@SPI</span>(<span 
class="hljs-string">"dubbo"</span>)
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span 
class="hljs-keyword">interface</span> <span class="hljs-title">Protocol</span> 
</span>{
+
+    <span class="hljs-function"><span class="hljs-keyword">int</span> <span 
class="hljs-title">getDefaultPort</span><span 
class="hljs-params">()</span></span>;
+
+    <span class="hljs-meta">@Adaptive</span>
+    &lt;T&gt; <span class="hljs-function">Exporter&lt;T&gt; <span 
class="hljs-title">export</span><span class="hljs-params">(Invoker&lt;T&gt; 
invoker)</span> <span class="hljs-keyword">throws</span> RpcException</span>;
+
+    <span class="hljs-meta">@Adaptive</span>
+    &lt;T&gt; <span class="hljs-function">Invoker&lt;T&gt; <span 
class="hljs-title">refer</span><span class="hljs-params">(Class&lt;T&gt; type, 
URL url)</span> <span class="hljs-keyword">throws</span> RpcException</span>;
+
+    <span class="hljs-function"><span class="hljs-keyword">void</span> <span 
class="hljs-title">destroy</span><span class="hljs-params">()</span></span>;
+</code></pre>
+<p>As you can see, there are four methods in the Protocol interface, but only 
the methods of export and refer use the @adaptive annotation. Dubbo 
automatically generates adaptive instances, and only the methods modified by 
@Adaptive has a specific implementation. Therefore, in the Protocol$Adpative 
class, only the export and refer methods have specific implementations, and the 
rest of the methods throw exceptions.</p>
+</section><footer class="footer-container" data-reactid="19"><div 
class="footer-body" data-reactid="20"><img src="/img/dubbo_gray.png" 
data-reactid="21"/><img class="apache" src="/img/apache_logo.png" 
data-reactid="22"/><div class="cols-container" data-reactid="23"><div 
class="col col-12" data-reactid="24"><h3 data-reactid="25">Disclaimer</h3><p 
data-reactid="26">Apache Dubbo is an effort undergoing incubation at The Apache 
Software Foundation (ASF), sponsored by the Incubator. Incubatio [...]
+       <script 
src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js";></script>
+       <script 
src="https://f.alicdn.com/react/15.4.1/react-dom.min.js";></script>
+       <script>
+               window.rootPath = '';
+  </script>
+  <script src="/build/blogDetail.js"></script>
+  <!-- Global site tag (gtag.js) - Google Analytics -->
+       <script async 
src="https://www.googletagmanager.com/gtag/js?id=UA-112489517-1";></script>
+       <script>
+               window.dataLayer = window.dataLayer || [];
+               function gtag(){dataLayer.push(arguments);}
+               gtag('js', new Date());
+
+               gtag('config', 'UA-112489517-1');
+       </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/en-us/blog/introduction-to-dubbo-spi-2.json 
b/en-us/blog/introduction-to-dubbo-spi-2.json
new file mode 100644
index 0000000..918b890
--- /dev/null
+++ b/en-us/blog/introduction-to-dubbo-spi-2.json
@@ -0,0 +1,4 @@
+{
+  "filename": "introduction-to-dubbo-spi-2.md",
+  "__html": "<h1>Dubbo extensible mechanism source code 
analysis</h1>\n<hr>\n<p>In the <a 
href=\"#/blog/introduction-to-dubbo-spi.md\">actual implementation of the Dubbo 
extensibility mechanism</a>, we learned some concepts of the Dubbo extension 
mechanism, explored the implementation of LoadBalance in Dubbo, and implemented 
a LoadBalance on our own. Do you think Dubbo's extension mechanism is great? 
Next, we will go deep into the source code of Dubbo and see what it 
is.</p>\n<h1>Extensi [...]
+}
\ No newline at end of file
diff --git a/site_config/blog.js b/site_config/blog.js
index 46e0723..94f7aca 100644
--- a/site_config/blog.js
+++ b/site_config/blog.js
@@ -4,6 +4,13 @@ export default {
     postsTitle: 'All posts',
     list: [
         {
+            title: 'How to implement a fully asynchronous calls chain based on 
Dubbo',
+            author: '@Siqi Zhuo',
+            dateStr: 'Aug 13th, 2018',
+            desc: 'Introduce the new feature of implementing the full 
asynchronous programming in Dubbo 2.7.0, mainly about previous asynchronous 
method before 2.6.x versions, enhancement in version 2.7.0 and a few examples 
to demonstrate its usage',
+            link: '/en-us/blog/dubbo-new-async.html',
+        },
+        {
             title: 'Generic invoke of Dubbo',
             author: '@ChasePGit',
             dateStr: 'August 14th,2018',
@@ -54,7 +61,7 @@ export default {
       },
       {
         title: 'Sentinel: The flow sentinel of Dubbo services',
-        author: 'Eric Zhao',
+        author: '@Eric Zhao',
         dateStr: 'July 27th, 2018',
         desc: 'This blog introduces to the Sentinel and its best practice with 
Dubbo services. Sentinel is a powerful library that takes "flow" as the 
breakthrough point, and covers multiple fields including flow control, circuit 
breaking and load protection to guarantee service stability.',
         link: '/en-us/blog/sentinel-introduction-for-dubbo.html',
@@ -75,56 +82,56 @@ export default {
       },
       {
         title: 'The ApacheCon NA schedule has been announced',
-        author: 'Huxing Zhang',
+        author: '@Huxing Zhang',
         dateStr: 'May 2nd,2018',
         desc: 'Ian Luo and Jun Liu will talk about "Introducing Apache 
Dubbo(Incubating): What is Dubbo and How it Works" at ApacheCon NA this year in 
Montréal!',
         link: '/en-us/blog/apachecon-na-2018.html',
       },
       {
         title: 'The GSoC (Google Summer of Code) 2018 projects has been 
announced',
-        author: 'Huxing Zhang',
+        author: '@Huxing Zhang',
         dateStr: 'April 25th,2018',
         desc: 'Raghu Reddy\'s project "Extending Serialization protocols 
support for Apache Dubbo" has been accepted! Congratulations!',
         link: '/en-us/blog/gsoc-2018.html',
       },
       {
         title: 'Dubbo roadmap is announced in QCon Beijing 2018',
-        author: 'Huxing Zhang',
+        author: '@Huxing Zhang',
         dateStr: 'April 22nd,2018',
         desc: 'Ian Luo has delivered a great talk at QCon Beijing 2018, where 
the roadmap of Dubbo has also be announced',
         link: '/en-us/blog/qcon-beijing-2018.html',
       },
       {
         title: 'Introduction to Dubbo spi ',
-        author: 'wangxuekui',
+        author: '@wangxuekui',
         dateStr: 'August 9th, 2018',
         desc: 'We have introduction to Dubbo spi.',
         link: '/en-us/blog/introduction-to-dubbo-spi.html',
       },
       {
         title: 'Manipulating Services Dynamically via QoS',
-        author: 'Wendell Hu (@wendzhue)',
+        author: '@Wendell Hu (@wendzhue)',
         dateStr: 'August 14th, 2018',
         desc: 'This blog introduces how to use QoS of Dubbo to configure 
services dynamically, and QoS\'s parameters and ways to configure',
         link: '/en-us/blog/introduction-to-dubbo-qos.html',
       },
       {
         title: 'Use annotation in Dubbo',
-        author: 'Ge Shao',
+        author: '@Ge Shao',
         dateStr: 'August 7nd,2018',
         desc: 'This blog introduces how to use annotations',
         link: '/en-us/blog/dubbo-annotation.html',
       },
       {
         title: 'Using Zookeeper in Dubbo',
-        author: 'Mani',
+        author: '@Mani',
         dateStr: 'August 7th,2018',
         desc: 'This blog introduces how to use Zookeeper in Dubbo',
         link: '/en-us/blog/dubbo-zk.html',
       },
       {
         title: 'Your First Dubbo Demo',
-        author: 'Yang Xinru',
+        author: '@Yang Xinru',
         dateStr: 'August 7th,2018',
         desc: 'Your First Dubbo Demo',
         link: '/en-us/blog/dubbo-101.html',
@@ -151,7 +158,7 @@ export default {
         },
         {
             title: 'Dubbo的负载均衡',
-            author: '@leiwei',
+            author: '@vangoleo',
             dateStr: 'August 10th, 2018',
             desc: '本文介绍了负载均衡的相关概念以及 Dubbo 中的负载均衡策略实现',
             link: '/zh-cn/blog/dubbo-loadbalance.html',
@@ -179,7 +186,7 @@ export default {
       },
         {
         title: '通过QoS对服务进行动态控制',
-        author: 'Huxing Zhang',
+        author: '@Huxing Zhang',
         dateStr: 'August 2nd, 2018',
         desc: '介绍了如何使用Dubbo的QoS功能对服务进行动态配置,以及相关的参数及配置方式。',
         link: '/zh-cn/blog/introduction-to-dubbo-qos.html',
@@ -193,14 +200,14 @@ export default {
       },
       {
         title: '从跨语言调用到 dubbo2.js',
-        author: '徐靖峰',
+        author: '@徐靖峰',
         dateStr: 'July 27th, 2018',
         desc: '如何使用 dubbo2.js 进行跨语言的 dubbo 调用',
         link: '/zh-cn/blog/dubbo2-js.html',
       },
       {
         title: 'Sentinel 为 Dubbo 服务保驾护航',
-        author: 'Eric Zhao',
+        author: '@Eric Zhao',
         dateStr: 'July 24th, 2018',
         desc: '主要介绍了面向分布式服务架构的轻量级流量控制组件 Sentinel 以及在 Dubbo 中整合使用 Sentinel 
的最佳实践。',
         link: '/zh-cn/blog/sentinel-introduction-for-dubbo.html',
@@ -235,7 +242,7 @@ export default {
       },
       {
         title: 'Spring Boot+Dubbo应用启停源码分析',
-        author: 'Huxing Zhang',
+        author: '@Huxing Zhang',
         dateStr: 'May 28th, 2018',
         desc: 'dubbo-spring-boot-project致力于简化 Dubbo RPC 框架在Spring 
Boot应用场景的开发,同时也整合了Spring Boot特性。',
         link: '/zh-cn/blog/spring-boot-dubbo-start-stop-analysis.html',
@@ -256,17 +263,11 @@ export default {
       },
       {
         title: 'Dubbo可扩展机制源码解析',
-        author: '@hengyunabc',
+        author: '@vangoleo',
         dateStr: 'May 10th, 2018',
         desc: 
'在前面的博客中,我们了解了Dubbo扩展机制的一些概念,初探了Dubbo中LoadBalance的实现,并自己实现了一个LoadBalance。接下来,我们就深入Dubbo的源码,一睹庐山真面目。',
         link: '/zh-cn/blog/introduction-to-dubbo-spi-2.html',
-      },
-      {
-        title: 'How to implement a fully asynchronous calls chain based on 
Dubbo',
-        author: 'Siqi Zhuo',
-        dateStr: 'Aug 13th, 2018',
-        desc: 'Introduce the new feature of implementing the full asynchronous 
programming in Dubbo 2.7.0, mainly about previous asynchronous method before 
2.6.x versions, enhancement in version 2.7.0 and a few examples to demonstrate 
its usage',
-        link: 
'/blog/en-us/how-to-implement-full-asynchronous-call-chain-based-on-dubbo.md',
+      }
     ]
   },
 };
diff --git a/zh-cn/blog/dubbo-new-async.html b/zh-cn/blog/dubbo-new-async.html
index 9646974..89b9919 100644
--- a/zh-cn/blog/dubbo-new-async.html
+++ b/zh-cn/blog/dubbo-new-async.html
@@ -12,7 +12,7 @@
        <link rel="stylesheet" href="/build/blogDetail.css" />
 </head>
 <body>
-       <div id="root"><div class="blog-detail-page" data-reactroot="" 
data-reactid="1" data-react-checksum="-2039027517"><header 
class="header-container header-container-normal" data-reactid="2"><div 
class="header-body" data-reactid="3"><a href="/zh-cn/index.html" 
data-reactid="4"><img class="logo" src="/img/dubbo_colorful.png" 
data-reactid="5"/></a><span class="language-switch language-switch-normal" 
data-reactid="6">En</span><div class="header-menu" data-reactid="7"><img 
class="header-menu-t [...]
+       <div id="root"><div class="blog-detail-page" data-reactroot="" 
data-reactid="1" data-react-checksum="-532878396"><header 
class="header-container header-container-normal" data-reactid="2"><div 
class="header-body" data-reactid="3"><a href="/zh-cn/index.html" 
data-reactid="4"><img class="logo" src="/img/dubbo_colorful.png" 
data-reactid="5"/></a><span class="language-switch language-switch-normal" 
data-reactid="6">En</span><div class="header-menu" data-reactid="7"><img 
class="header-menu-to [...]
 
<p>基于Dubbo实现全异步编程,是在2.7.0版本中对现有异步方式增强后新引入的功能。本文先是回顾2.6.x及之前版本对异步的支持情况及存在的问题,引出了2.7.0版本基于CompletableFuture做了哪些针对性的增强,通过几个示例详细阐述了增强后的异步编程的使用方式,最后总结了引入异步模式带来的新问题及Dubbo的解决方法。通过阅读这篇文章,可以很容易的基于Dubbo2.7.0+版本实现一个全异步的远程服务调用链路。</p>
 <h2>2.6.x版本之前的异步方式</h2>
 <p>在2.6.x及之前的版本提供了一定的异步编程能力,包括Consumer端<a 
href="http://dubbo.apache.org/books/dubbo-user-book/demos/async-call.html";>异步调用</a>、<a
 
href="http://dubbo.apache.org/books/dubbo-user-book/demos/callback-parameter.html";>参数回调</a>、<a
 
href="http://dubbo.apache.org/books/dubbo-user-book/demos/events-notify.html";>事件通知</a>等,在上面的文档链接中有关于使用方式的简单介绍和Demo。</p>
@@ -34,7 +34,7 @@
       &lt;dubbo:method name=&quot;findFoo&quot; async=&quot;true&quot; /&gt;
 &lt;/dubbo:reference&gt;
 </code></pre>
-<ol>
+<ol start="2">
 <li>通过RpcContext获取Future</li>
 </ol>
 <pre><code>// 此调用会立即返回null
diff --git a/zh-cn/blog/dubbo-new-async.json b/zh-cn/blog/dubbo-new-async.json
index 66d1b8a..d9b63c4 100644
--- a/zh-cn/blog/dubbo-new-async.json
+++ b/zh-cn/blog/dubbo-new-async.json
@@ -1,4 +1,4 @@
 {
   "filename": "dubbo-new-async.md",
-  "__html": 
"<h1>如何基于Dubbo实现全异步调用链</h1>\n<p>基于Dubbo实现全异步编程,是在2.7.0版本中对现有异步方式增强后新引入的功能。本文先是回顾2.6.x及之前版本对异步的支持情况及存在的问题,引出了2.7.0版本基于CompletableFuture做了哪些针对性的增强,通过几个示例详细阐述了增强后的异步编程的使用方式,最后总结了引入异步模式带来的新问题及Dubbo的解决方法。通过阅读这篇文章,可以很容易的基于Dubbo2.7.0+版本实现一个全异步的远程服务调用链路。</p>\n<h2>2.6.x版本之前的异步方式</h2>\n<p>在2.6.x及之前的版本提供了一定的异步编程能力,包括Consumer端<a
 
href=\"http://dubbo.apache.org/books/dubbo-user-book/demos/async-call.html\";>异步调用</a>、<a
 href=\"http://dubbo.apache.org/books/dubbo-user-book/demos/callback-para [...]
+  "__html": 
"<h1>如何基于Dubbo实现全异步调用链</h1>\n<p>基于Dubbo实现全异步编程,是在2.7.0版本中对现有异步方式增强后新引入的功能。本文先是回顾2.6.x及之前版本对异步的支持情况及存在的问题,引出了2.7.0版本基于CompletableFuture做了哪些针对性的增强,通过几个示例详细阐述了增强后的异步编程的使用方式,最后总结了引入异步模式带来的新问题及Dubbo的解决方法。通过阅读这篇文章,可以很容易的基于Dubbo2.7.0+版本实现一个全异步的远程服务调用链路。</p>\n<h2>2.6.x版本之前的异步方式</h2>\n<p>在2.6.x及之前的版本提供了一定的异步编程能力,包括Consumer端<a
 
href=\"http://dubbo.apache.org/books/dubbo-user-book/demos/async-call.html\";>异步调用</a>、<a
 href=\"http://dubbo.apache.org/books/dubbo-user-book/demos/callback-para [...]
 }
\ No newline at end of file
diff --git a/zh-cn/blog/index.html b/zh-cn/blog/index.html
index 2a7242c..b16a519 100644
--- a/zh-cn/blog/index.html
+++ b/zh-cn/blog/index.html
@@ -12,7 +12,7 @@
        <link rel="stylesheet" href="/build/blog.css" />
 </head>
 <body>
-       <div id="root"><div class="blog-list-page" data-reactroot="" 
data-reactid="1" data-react-checksum="721116974"><header 
class="header-container header-container-normal" data-reactid="2"><div 
class="header-body" data-reactid="3"><a href="/zh-cn/index.html" 
data-reactid="4"><img class="logo" src="/img/dubbo_colorful.png" 
data-reactid="5"/></a><span class="language-switch language-switch-normal" 
data-reactid="6">En</span><div class="header-menu" data-reactid="7"><img 
class="header-menu-toggl [...]
+       <div id="root"><div class="blog-list-page" data-reactroot="" 
data-reactid="1" data-react-checksum="2030919745"><header 
class="header-container header-container-normal" data-reactid="2"><div 
class="header-body" data-reactid="3"><a href="/zh-cn/index.html" 
data-reactid="4"><img class="logo" src="/img/dubbo_colorful.png" 
data-reactid="5"/></a><span class="language-switch language-switch-normal" 
data-reactid="6">En</span><div class="header-menu" data-reactid="7"><img 
class="header-menu-togg [...]
        <script 
src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js";></script>
        <script 
src="https://f.alicdn.com/react/15.4.1/react-dom.min.js";></script>
        <script>

Reply via email to