You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by je...@apache.org on 2018/09/04 08:46:43 UTC

[incubator-dubbo-website] branch asf-site updated: add compatible

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 469b327  add compatible
469b327 is described below

commit 469b3273df1925b34ab0b4d27270b0aefd572a0c
Author: zhuyong <yo...@alibaba-inc.com>
AuthorDate: Tue Sep 4 16:46:27 2018 +0800

    add compatible
---
 ...bbo-basic-usage-dubbo-provider-configuration.md |   2 +-
 blog/zh-cn/dubbo-compatible.md                     | 197 ++++++++++++++++++++
 blog/zh-cn/dubbo-contribue-to-opensource.md        |   2 +-
 blog/zh-cn/dubbo-meetup-chengdu.md                 |   4 +-
 blog/zh-cn/dubbo-meetup-shanghai-jun-23rd-2018.md  |   4 +-
 blog/zh-cn/dubbo-meetup-shenzhen.md                |   4 +-
 blog/zh-cn/introduction-to-dubbo-spi.md            |   1 -
 blog/zh-cn/optimization-branch-prediction.md       |   1 -
 build/blog.js                                      |   2 +-
 site_config/blog.js                                |   7 +
 ...o-basic-usage-dubbo-provider-configuration.html |   3 +-
 ...o-basic-usage-dubbo-provider-configuration.json |   2 +-
 zh-cn/blog/dubbo-compatible.html                   | 198 +++++++++++++++++++++
 zh-cn/blog/dubbo-compatible.json                   |   7 +
 zh-cn/blog/dubbo-contribue-to-opensource.html      |   3 +-
 zh-cn/blog/dubbo-contribue-to-opensource.json      |   2 +-
 zh-cn/blog/dubbo-meetup-chengdu.html               |   2 +-
 zh-cn/blog/dubbo-meetup-chengdu.json               |   2 +-
 .../blog/dubbo-meetup-shanghai-jun-23rd-2018.html  |   2 +-
 .../blog/dubbo-meetup-shanghai-jun-23rd-2018.json  |   2 +-
 zh-cn/blog/dubbo-meetup-shenzhen.html              |   2 +-
 zh-cn/blog/dubbo-meetup-shenzhen.json              |   2 +-
 zh-cn/blog/index.html                              |   2 +-
 zh-cn/blog/introduction-to-dubbo-spi.html          |   3 +-
 zh-cn/blog/introduction-to-dubbo-spi.json          |   2 +-
 zh-cn/blog/optimization-branch-prediction.html     |   3 +-
 zh-cn/blog/optimization-branch-prediction.json     |   2 +-
 27 files changed, 433 insertions(+), 30 deletions(-)

diff --git a/blog/zh-cn/dubbo-basic-usage-dubbo-provider-configuration.md b/blog/zh-cn/dubbo-basic-usage-dubbo-provider-configuration.md
index 09a9a45..e4349f5 100644
--- a/blog/zh-cn/dubbo-basic-usage-dubbo-provider-configuration.md
+++ b/blog/zh-cn/dubbo-basic-usage-dubbo-provider-configuration.md
@@ -5,7 +5,7 @@ description: 主要讲述如何配置dubbo,按照配置方式上可以分为
 ---
 
 # Dubbo基本用法之Provider配置
----
+
 
 ## Dubbo基本用法
 
diff --git a/blog/zh-cn/dubbo-compatible.md b/blog/zh-cn/dubbo-compatible.md
new file mode 100644
index 0000000..dd64448
--- /dev/null
+++ b/blog/zh-cn/dubbo-compatible.md
@@ -0,0 +1,197 @@
+---
+title: Dubbo 2.7.x repackage后的兼容实现方案
+keywords: Dubbo, repackage, 兼容
+description: 本文简单描述了2.7.x repackage后对老版本的兼容性实现方案。
+---
+
+# Dubbo 2.7.x repackage后的兼容实现方案
+
+Dubbo至加入Apache孵化器以来,一个很强的诉求就是需要rename groupId和package name,这两项工作在项目毕业前需要完成。其中rename package相对来说复杂一些,除了要修改所有类的包名为`org.apache.dubbo`外,更多的是需要考虑如何老版本的兼容性。
+
+常见的兼容性包括但不限于以下几种情况:
+
+* 用户API
+  * 编程API
+  * Spring注解
+* 扩展SPI
+  * 扩展Filter
+
+2.7.x里就是通过增加了一个新的模块`dubbo-compatible`来解决以上兼容性问题。
+
+## 编程使用API
+
+编程使用API是最直接最原始的使用方式,其他方式诸如Spring schema、注解等方式都是基于原始API的;因此非常有必要对API编程形式进行兼容。
+
+所有编程相关API的兼容代码均在`com.alibaba.dubbo.config`包下,下面我们看看几个常见API的兼容实现。
+
+### ApplicationConfig
+
+```java
+package com.alibaba.dubbo.config;
+
+@Deprecated
+public class ApplicationConfig extends org.apache.dubbo.config.ApplicationConfig {
+
+    public ApplicationConfig() {
+        super();
+    }
+
+    public ApplicationConfig(String name) {
+        super(name);
+    }
+}
+```
+
+### ProtocolConfig
+
+```java
+package com.alibaba.dubbo.config;
+
+@Deprecated
+public class ProtocolConfig extends org.apache.dubbo.config.ProtocolConfig {
+
+    public ProtocolConfig() {
+    }
+
+    public ProtocolConfig(String name) {
+        super(name);
+    }
+
+    public ProtocolConfig(String name, int port) {
+        super(name, port);
+    }
+}
+```
+
+可以看到:
+
+1. 兼容类是直接通过继续repacakge后的类,达到最大程度的代码复用;
+2. 构造函数也需要保持兼容;
+
+整个兼容包中,除了上述API以外,包括一些常用的类比如`Constants`、`URL`以及绝大部分的兼容类都是通过简单的继承,让用户基于老的API实现的类能正确运行。
+
+## Spring注解
+
+Spring注解诸如`@EnableDubbo`、`@Service`以及`@Reference`,由于不能使用继承,故这些注解类是通过代码拷贝来实现的;用于处理这些注解的Spring BeanPostProcessor以及Parser等相关的类,也是通过拷贝来实现;
+
+这类兼容代码分别位于兼容包的以下几个package中:
+
+* com.alibaba.dubbo.config.annotation
+* com.alibaba.dubbo.config.spring.context.annotation
+* org.apache.dubbo.config.spring
+
+所以这里要特别强调的是,这类代码在2.7.x里存在2份,因此有修改的同时需要同步修改。
+
+## 扩展SPI
+
+Dubbo的SPI扩展机制,可以通过[Dubbo可扩展机制实战](http://dubbo.apache.org/zh-cn/blog/introduction-to-dubbo-spi.html)这篇博客详细了解。
+
+以Filter扩展为例,简单来说就是:
+
+1. MyFilter需要实现Filter接口
+2. 在META-INF/dubbo下,增加META-INF/dubbo/com.alibaba.dubbo.rpc.Filter,内容为:
+
+	```
+	myFilter=com.test.MyFilter
+	```
+
+看似简单的两点,对Dubbo框架来说,需要:
+
+1. 正确加载配置文件META-INF/dubbo/com.alibaba.dubbo.rpc.Filter
+2. 正确加载MyFilter类并执行invoke方法
+
+下面分别介绍Dubbo框架怎么实现以上几点。
+
+### 正确加载META-INF/dubbo/com.alibaba.dubbo.rpc.Filter
+
+Dubbo SPI机制在查找配置文件时,是根据扩展点的类名来查找的,以Filter为例,在包名变为org.apache.dubbo后,查询的目录变成:
+
+* META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter
+* META-INF/dubbo/org.apache.dubbo.rpc.Filter
+* META-INF/services/org.apache.dubbo.rpc.Filter
+
+但是用户之前按老的包实现的Filter,其配置是放在类似`META-INF/dubbo/com.alibaba.dubbo.rpc.Filter`的,如果框架不做特殊处理,是不会加载老配置的。
+
+因此在`ExtensionLoader`这个类里,做了特殊的处理:
+
+```java
+    // synchronized in getExtensionClasses
+    private Map<String, Class<?>> loadExtensionClasses() {
+        final SPI defaultAnnotation = type.getAnnotation(SPI.class);
+        if (defaultAnnotation != null) {
+            String value = defaultAnnotation.value();
+            if ((value = value.trim()).length() > 0) {
+                String[] names = NAME_SEPARATOR.split(value);
+                if (names.length > 1) {
+                    throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()
+                            + ": " + Arrays.toString(names));
+                }
+                if (names.length == 1) cachedDefaultName = names[0];
+            }
+        }
+
+        Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
+        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
+        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
+        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());
+        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
+        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
+        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
+        return extensionClasses;
+    }
+```
+
+可以看到,除了加载新配置外,老配置文件也会进行扫描。
+
+### 正确加载MyFilter类
+
+`com.alibaba.dubbo.rpc.Filter`接口除了要继承自`org.apache.dubbo.rpc.Filter`以外,其唯一的方法invoke也需要做特殊处理。我们看看它的方法签名:
+
+`Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException;`
+
+这里参数、返回值、异常都会被实现类`MyFilter`用到,因此这些类也需要有兼容类;而参数、返回值不同,对于接口来说是不同的方法,因此:
+
+* 需要在com.alibaba.dubbo.rpc.Filter里,定义老的invoke方法,MyFilter会覆盖这个方法;
+* org.apache.dubbo.rpc.Filter里的invoke方法,需要找一个地方来实现桥接,框架调用Filter链执行到新的invoke方法时,新的参数如何转换成老参数,老返回值如何转换成新的返回值;
+
+这里就用到了JDK8的新特性:接口default方法。
+
+```java
+@Deprecated
+public interface Filter extends org.apache.dubbo.rpc.Filter {
+
+    Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException;
+
+    default org.apache.dubbo.rpc.Result invoke(org.apache.dubbo.rpc.Invoker<?> invoker,
+                                               org.apache.dubbo.rpc.Invocation invocation)
+            throws org.apache.dubbo.rpc.RpcException {
+        Result.CompatibleResult result = (Result.CompatibleResult) invoke(new Invoker.CompatibleInvoker<>(invoker),
+                new Invocation.CompatibleInvocation(invocation));
+        return result.getDelegate();
+    }
+}
+```
+
+可以看到,default方法里,对参数进行了包装,然后调用老的invoke方法,并将返回值进行解包后返回给Dubbo框架。这里Result.CompatibleResult、Invocation.CompatibleInvocation以及Invoker.CompatibleInvoker都用到了代理模式。
+
+感兴趣的同学可以详细看一下以下几个类:
+
+* com.alibaba.dubbo.rpc.Invocation
+* com.alibaba.dubbo.rpc.Invoker
+* com.alibaba.dubbo.rpc.Result
+
+## 后续todo list
+
+目前兼容包仅仅是对常见的API及SPI做了支持,列表如下:
+
+* com.alibaba.dubbo.rpc.Filter / Invocation / Invoker / Result / RpcContext / RpcException
+* com.alibaba.dubbo.config.*Config
+* com.alibaba.dubbo.config.annotation.Reference / Service
+* com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo
+* com.alibaba.dubbo.common.Constants / URL
+* com.alibaba.dubbo.common.extension.ExtensionFactory
+* com.alibaba.dubbo.common.serialize.Serialization / ObjectInput / ObjectOutput
+* com.alibaba.dubbo.cache.CacheFactory / Cache
+* com.alibaba.dubbo.rpc.service.EchoService / GenericService
+
+大家如果在试用的过程中发现有任何问题请及时提出;同时如果对其他扩展点有兼容需求,也请大家提出来,也非常欢迎大家自己解决并贡献出来。
\ No newline at end of file
diff --git a/blog/zh-cn/dubbo-contribue-to-opensource.md b/blog/zh-cn/dubbo-contribue-to-opensource.md
index 57916d8..68d7985 100644
--- a/blog/zh-cn/dubbo-contribue-to-opensource.md
+++ b/blog/zh-cn/dubbo-contribue-to-opensource.md
@@ -5,7 +5,7 @@ description: 本文将会以 incubator-dubbo 项目为例向你阐释,给开
 ---
 
 # 以Dubbo为例,聊聊如何向开源项目做贡献
----
+
 
 Github 上有众多优秀的开源项目,大多数 IT 从业者将其当做了予取予求的工具库,遇到什么需求,先去 Github 搜一把,但有没有想过有一天自己也可以给开源事业做一些贡献呢?本文将会以 incubator-dubbo 项目为例,向你阐释,给开源项目做贡献并不是一件难事。
 
diff --git a/blog/zh-cn/dubbo-meetup-chengdu.md b/blog/zh-cn/dubbo-meetup-chengdu.md
index 99c2af2..15d3aa6 100644
--- a/blog/zh-cn/dubbo-meetup-chengdu.md
+++ b/blog/zh-cn/dubbo-meetup-chengdu.md
@@ -4,8 +4,8 @@ keywords: Dubbo, 成都, meetup
 description: 第四届Dubbo开发者沙龙将于8月26日在成都举行。
 ---
 
-第四届Dubbo开发者沙龙将于8月26日在成都举行
----
+# 第四届Dubbo开发者沙龙将于8月26日在成都举行
+
 
 Aliware Open Source•成都站-Apache Dubbo开发者沙龙将于8月26日(周日)在成都高新区天府五街200号菁蓉国际广场8号楼2楼会议厅举办,技术GG们的思想盛宴,干货与福利一个都不会少。
 
diff --git a/blog/zh-cn/dubbo-meetup-shanghai-jun-23rd-2018.md b/blog/zh-cn/dubbo-meetup-shanghai-jun-23rd-2018.md
index 9f58089..612f285 100644
--- a/blog/zh-cn/dubbo-meetup-shanghai-jun-23rd-2018.md
+++ b/blog/zh-cn/dubbo-meetup-shanghai-jun-23rd-2018.md
@@ -1,5 +1,5 @@
-第二届Dubbo开发者沙龙在上海成功举办
----
+# 第二届Dubbo开发者沙龙在上海成功举办
+
 
 第二届Dubbo开发者沙龙在上海成功举办,超过700位开发者报名,现场参与人数300+,通过阿里云天池、云栖社区、大咖说引导线上直播观看次数10000+
 
diff --git a/blog/zh-cn/dubbo-meetup-shenzhen.md b/blog/zh-cn/dubbo-meetup-shenzhen.md
index 29a9fba..7c14e41 100644
--- a/blog/zh-cn/dubbo-meetup-shenzhen.md
+++ b/blog/zh-cn/dubbo-meetup-shenzhen.md
@@ -1,5 +1,5 @@
-第三届Dubbo开发者沙龙在深圳成功举办
----
+# 第三届Dubbo开发者沙龙在深圳成功举办
+
 
 第三届Dubbo开发者沙龙在深圳成功举办,超过2000位开发者报名,现场参与人数700+,通过阿里云天池、云栖社区、大咖说引导线上直播观看次数17000+
 
diff --git a/blog/zh-cn/introduction-to-dubbo-spi.md b/blog/zh-cn/introduction-to-dubbo-spi.md
index a97ab54..29ac721 100644
--- a/blog/zh-cn/introduction-to-dubbo-spi.md
+++ b/blog/zh-cn/introduction-to-dubbo-spi.md
@@ -5,7 +5,6 @@ description: 本文介绍了Dubbo框架的核心,SPI扩展机制。
 ---
 
 # Dubbo可扩展机制实战
----
 
 ## 1. Dubbo的扩展机制
 在Dubbo的官网上,Dubbo描述自己是一个高性能的RPC框架。今天我想聊聊Dubbo的另一个很棒的特性, 就是它的可扩展性。
diff --git a/blog/zh-cn/optimization-branch-prediction.md b/blog/zh-cn/optimization-branch-prediction.md
index eb9e615..d0f737d 100644
--- a/blog/zh-cn/optimization-branch-prediction.md
+++ b/blog/zh-cn/optimization-branch-prediction.md
@@ -3,7 +3,6 @@ title: 提前if判断帮助CPU分支预测
 ---
 
 # 优化技巧:提前if判断帮助CPU分支预测
----
 
 ## 分支预测
 
diff --git a/build/blog.js b/build/blog.js
index 29e02b2..bd221da 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/site_config/blog.js b/site_config/blog.js
index f5aa1eb..eb18d80 100644
--- a/site_config/blog.js
+++ b/site_config/blog.js
@@ -157,6 +157,13 @@ export default {
     postsTitle: '所有文章',
     list: [
 		{
+		    title: 'Dubbo 2.7.x repackage后的兼容实现方案',
+		    author:'@jerrick',
+		    dateStr: 'Sep 4th, 2018',
+		    desc: '本文简单描述了2.7.x repackage后对老版本的兼容性实现方案。',
+		    link: '/zh-cn/blog/dubbo-compatible.html',
+		},
+		{
 		    title: 'Dubbo与Kubernetes集成',
 		    author:'@kongming',
 		    dateStr: 'Sep 4th, 2018',
diff --git a/zh-cn/blog/dubbo-basic-usage-dubbo-provider-configuration.html b/zh-cn/blog/dubbo-basic-usage-dubbo-provider-configuration.html
index 3238454..4740475 100644
--- a/zh-cn/blog/dubbo-basic-usage-dubbo-provider-configuration.html
+++ b/zh-cn/blog/dubbo-basic-usage-dubbo-provider-configuration.html
@@ -12,8 +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="-1082635303"><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 [...]
-<hr>
+	<div id="root"><div class="blog-detail-page" data-reactroot="" data-reactid="1" data-react-checksum="-188396933"><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 [...]
 <h2>Dubbo基本用法</h2>
 <p>本章节主要讲述如何配置dubbo,按照配置方式上分,可以分为:XML配置,properties方式配置,注解方式配置,API调用方式配置。
 按照功能角度进行划分,可以分为Dubbo Provider和Dubbo Consumer。接下来章节中,分别对dubbo provider和Dubbo consumer进行讲解。</p>
diff --git a/zh-cn/blog/dubbo-basic-usage-dubbo-provider-configuration.json b/zh-cn/blog/dubbo-basic-usage-dubbo-provider-configuration.json
index d594b40..e2b56ef 100644
--- a/zh-cn/blog/dubbo-basic-usage-dubbo-provider-configuration.json
+++ b/zh-cn/blog/dubbo-basic-usage-dubbo-provider-configuration.json
@@ -1,6 +1,6 @@
 {
   "filename": "dubbo-basic-usage-dubbo-provider-configuration.md",
-  "__html": "<h1>Dubbo基本用法之Provider配置</h1>\n<hr>\n<h2>Dubbo基本用法</h2>\n<p>本章节主要讲述如何配置dubbo,按照配置方式上分,可以分为:XML配置,properties方式配置,注解方式配置,API调用方式配置。\n按照功能角度进行划分,可以分为Dubbo Provider和Dubbo Consumer。接下来章节中,分别对dubbo provider和Dubbo consumer进行讲解。</p>\n<h3>Dubbo Provider配置</h3>\n<h4>Provider 配置详解</h4>\n<p>配置Dubbo Provider有4种方式:XML配置,properties方式配置,API调用方式配置,注解方式配置。</p>\n<h5>XML配置</h5>\n<h6>最简单的配置的样例:</h6>\n<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\n&lt;beans xmlns=&qu [...]
+  "__html": "<h1>Dubbo基本用法之Provider配置</h1>\n<h2>Dubbo基本用法</h2>\n<p>本章节主要讲述如何配置dubbo,按照配置方式上分,可以分为:XML配置,properties方式配置,注解方式配置,API调用方式配置。\n按照功能角度进行划分,可以分为Dubbo Provider和Dubbo Consumer。接下来章节中,分别对dubbo provider和Dubbo consumer进行讲解。</p>\n<h3>Dubbo Provider配置</h3>\n<h4>Provider 配置详解</h4>\n<p>配置Dubbo Provider有4种方式:XML配置,properties方式配置,API调用方式配置,注解方式配置。</p>\n<h5>XML配置</h5>\n<h6>最简单的配置的样例:</h6>\n<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\n&lt;beans xmlns=&quot;htt [...]
   "title": "Dubbo基础用法之Provider配置",
   "keywords": "Dubbo, Provider, Configuration",
   "description": "主要讲述如何配置dubbo,按照配置方式上可以分为:XML配置,properties方式配置,注解方式配置,API调用方式配置。"
diff --git a/zh-cn/blog/dubbo-compatible.html b/zh-cn/blog/dubbo-compatible.html
new file mode 100644
index 0000000..3aa3306
--- /dev/null
+++ b/zh-cn/blog/dubbo-compatible.html
@@ -0,0 +1,198 @@
+<!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, repackage, 兼容" />
+	<meta name="description" content="本文简单描述了2.7.x repackage后对老版本的兼容性实现方案。" />
+	<!-- 网页标签标题 -->
+	<title>Dubbo 2.7.x repackage后的兼容实现方案</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="1373077449"><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至加入Apache孵化器以来,一个很强的诉求就是需要rename groupId和package name,这两项工作在项目毕业前需要完成。其中rename package相对来说复杂一些,除了要修改所有类的包名为<code>org.apache.dubbo</code>外,更多的是需要考虑如何老版本的兼容性。</p>
+<p>常见的兼容性包括但不限于以下几种情况:</p>
+<ul>
+<li>用户API
+<ul>
+<li>编程API</li>
+<li>Spring注解</li>
+</ul>
+</li>
+<li>扩展SPI
+<ul>
+<li>扩展Filter</li>
+</ul>
+</li>
+</ul>
+<p>2.7.x里就是通过增加了一个新的模块<code>dubbo-compatible</code>来解决以上兼容性问题。</p>
+<h2>编程使用API</h2>
+<p>编程使用API是最直接最原始的使用方式,其他方式诸如Spring schema、注解等方式都是基于原始API的;因此非常有必要对API编程形式进行兼容。</p>
+<p>所有编程相关API的兼容代码均在<code>com.alibaba.dubbo.config</code>包下,下面我们看看几个常见API的兼容实现。</p>
+<h3>ApplicationConfig</h3>
+<pre><code class="language-java"><span class="hljs-keyword">package</span> com.alibaba.dubbo.config;
+
+<span class="hljs-meta">@Deprecated</span>
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ApplicationConfig</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">org</span>.<span class="hljs-title">apache</span>.<span class="hljs-title">dubbo</span>.<span class="hljs-title">config</span>.<span class="hljs-title">ApplicationConfig</span> </span>{
+
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ApplicationConfig</span><span class="hljs-params">()</span> </span>{
+        <span class="hljs-keyword">super</span>();
+    }
+
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ApplicationConfig</span><span class="hljs-params">(String name)</span> </span>{
+        <span class="hljs-keyword">super</span>(name);
+    }
+}
+</code></pre>
+<h3>ProtocolConfig</h3>
+<pre><code class="language-java"><span class="hljs-keyword">package</span> com.alibaba.dubbo.config;
+
+<span class="hljs-meta">@Deprecated</span>
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProtocolConfig</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">org</span>.<span class="hljs-title">apache</span>.<span class="hljs-title">dubbo</span>.<span class="hljs-title">config</span>.<span class="hljs-title">ProtocolConfig</span> </span>{
+
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ProtocolConfig</span><span class="hljs-params">()</span> </span>{
+    }
+
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ProtocolConfig</span><span class="hljs-params">(String name)</span> </span>{
+        <span class="hljs-keyword">super</span>(name);
+    }
+
+    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ProtocolConfig</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> port)</span> </span>{
+        <span class="hljs-keyword">super</span>(name, port);
+    }
+}
+</code></pre>
+<p>可以看到:</p>
+<ol>
+<li>兼容类是直接通过继续repacakge后的类,达到最大程度的代码复用;</li>
+<li>构造函数也需要保持兼容;</li>
+</ol>
+<p>整个兼容包中,除了上述API以外,包括一些常用的类比如<code>Constants</code>、<code>URL</code>以及绝大部分的兼容类都是通过简单的继承,让用户基于老的API实现的类能正确运行。</p>
+<h2>Spring注解</h2>
+<p>Spring注解诸如<code>@EnableDubbo</code>、<code>@Service</code>以及<code>@Reference</code>,由于不能使用继承,故这些注解类是通过代码拷贝来实现的;用于处理这些注解的Spring BeanPostProcessor以及Parser等相关的类,也是通过拷贝来实现;</p>
+<p>这类兼容代码分别位于兼容包的以下几个package中:</p>
+<ul>
+<li>com.alibaba.dubbo.config.annotation</li>
+<li>com.alibaba.dubbo.config.spring.context.annotation</li>
+<li>org.apache.dubbo.config.spring</li>
+</ul>
+<p>所以这里要特别强调的是,这类代码在2.7.x里存在2份,因此有修改的同时需要同步修改。</p>
+<h2>扩展SPI</h2>
+<p>Dubbo的SPI扩展机制,可以通过<a href="http://dubbo.apache.org/zh-cn/blog/introduction-to-dubbo-spi.html">Dubbo可扩展机制实战</a>这篇博客详细了解。</p>
+<p>以Filter扩展为例,简单来说就是:</p>
+<ol>
+<li>
+<p>MyFilter需要实现Filter接口</p>
+</li>
+<li>
+<p>在META-INF/dubbo下,增加META-INF/dubbo/com.alibaba.dubbo.rpc.Filter,内容为:</p>
+<pre><code>myFilter=com.test.MyFilter
+</code></pre>
+</li>
+</ol>
+<p>看似简单的两点,对Dubbo框架来说,需要:</p>
+<ol>
+<li>正确加载配置文件META-INF/dubbo/com.alibaba.dubbo.rpc.Filter</li>
+<li>正确加载MyFilter类并执行invoke方法</li>
+</ol>
+<p>下面分别介绍Dubbo框架怎么实现以上几点。</p>
+<h3>正确加载META-INF/dubbo/com.alibaba.dubbo.rpc.Filter</h3>
+<p>Dubbo SPI机制在查找配置文件时,是根据扩展点的类名来查找的,以Filter为例,在包名变为org.apache.dubbo后,查询的目录变成:</p>
+<ul>
+<li>META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter</li>
+<li>META-INF/dubbo/org.apache.dubbo.rpc.Filter</li>
+<li>META-INF/services/org.apache.dubbo.rpc.Filter</li>
+</ul>
+<p>但是用户之前按老的包实现的Filter,其配置是放在类似<code>META-INF/dubbo/com.alibaba.dubbo.rpc.Filter</code>的,如果框架不做特殊处理,是不会加载老配置的。</p>
+<p>因此在<code>ExtensionLoader</code>这个类里,做了特殊的处理:</p>
+<pre><code class="language-java">    <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 = 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-string">": "</span> + Arrays.toString(names));
+                }
+                <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;();
+        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
+        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace(<span class="hljs-string">"org.apache"</span>, <span class="hljs-string">"com.alibaba"</span>));
+        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());
+        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace(<span class="hljs-string">"org.apache"</span>, <span class="hljs-string">"com.alibaba"</span>));
+        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
+        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace(<span class="hljs-string">"org.apache"</span>, <span class="hljs-string">"com.alibaba"</span>));
+        <span class="hljs-keyword">return</span> extensionClasses;
+    }
+</code></pre>
+<p>可以看到,除了加载新配置外,老配置文件也会进行扫描。</p>
+<h3>正确加载MyFilter类</h3>
+<p><code>com.alibaba.dubbo.rpc.Filter</code>接口除了要继承自<code>org.apache.dubbo.rpc.Filter</code>以外,其唯一的方法invoke也需要做特殊处理。我们看看它的方法签名:</p>
+<p><code>Result invoke(Invoker&lt;?&gt; invoker, Invocation invocation) throws RpcException;</code></p>
+<p>这里参数、返回值、异常都会被实现类<code>MyFilter</code>用到,因此这些类也需要有兼容类;而参数、返回值不同,对于接口来说是不同的方法,因此:</p>
+<ul>
+<li>需要在com.alibaba.dubbo.rpc.Filter里,定义老的invoke方法,MyFilter会覆盖这个方法;</li>
+<li>org.apache.dubbo.rpc.Filter里的invoke方法,需要找一个地方来实现桥接,框架调用Filter链执行到新的invoke方法时,新的参数如何转换成老参数,老返回值如何转换成新的返回值;</li>
+</ul>
+<p>这里就用到了JDK8的新特性:接口default方法。</p>
+<pre><code class="language-java"><span class="hljs-meta">@Deprecated</span>
+<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Filter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">org</span>.<span class="hljs-title">apache</span>.<span class="hljs-title">dubbo</span>.<span class="hljs-title">rpc</span>.<span class="hljs-title">Filter</span> </span>{
+
+    <span class="hljs-function">Result <span class="hljs-title">invoke</span><span class="hljs-params">(Invoker&lt;?&gt; invoker, Invocation invocation)</span> <span class="hljs-keyword">throws</span> RpcException</span>;
+
+    <span class="hljs-keyword">default</span> org.apache.dubbo.rpc.<span class="hljs-function">Result <span class="hljs-title">invoke</span><span class="hljs-params">(org.apache.dubbo.rpc.Invoker&lt;?&gt; invoker,
+                                               org.apache.dubbo.rpc.Invocation invocation)</span>
+            <span class="hljs-keyword">throws</span> org.apache.dubbo.rpc.RpcException </span>{
+        Result.CompatibleResult result = (Result.CompatibleResult) invoke(<span class="hljs-keyword">new</span> Invoker.CompatibleInvoker&lt;&gt;(invoker),
+                <span class="hljs-keyword">new</span> Invocation.CompatibleInvocation(invocation));
+        <span class="hljs-keyword">return</span> result.getDelegate();
+    }
+}
+</code></pre>
+<p>可以看到,default方法里,对参数进行了包装,然后调用老的invoke方法,并将返回值进行解包后返回给Dubbo框架。这里Result.CompatibleResult、Invocation.CompatibleInvocation以及Invoker.CompatibleInvoker都用到了代理模式。</p>
+<p>感兴趣的同学可以详细看一下以下几个类:</p>
+<ul>
+<li>com.alibaba.dubbo.rpc.Invocation</li>
+<li>com.alibaba.dubbo.rpc.Invoker</li>
+<li>com.alibaba.dubbo.rpc.Result</li>
+</ul>
+<h2>后续todo list</h2>
+<p>目前兼容包仅仅是对常见的API及SPI做了支持,列表如下:</p>
+<ul>
+<li>com.alibaba.dubbo.rpc.Filter / Invocation / Invoker / Result / RpcContext / RpcException</li>
+<li>com.alibaba.dubbo.config.*Config</li>
+<li>com.alibaba.dubbo.config.annotation.Reference / Service</li>
+<li>com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo</li>
+<li>com.alibaba.dubbo.common.Constants / URL</li>
+<li>com.alibaba.dubbo.common.extension.ExtensionFactory</li>
+<li>com.alibaba.dubbo.common.serialize.Serialization / ObjectInput / ObjectOutput</li>
+<li>com.alibaba.dubbo.cache.CacheFactory / Cache</li>
+<li>com.alibaba.dubbo.rpc.service.EchoService / GenericService</li>
+</ul>
+<p>大家如果在试用的过程中发现有任何问题请及时提出;同时如果对其他扩展点有兼容需求,也请大家提出来,也非常欢迎大家自己解决并贡献出来。</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/zh-cn/blog/dubbo-compatible.json b/zh-cn/blog/dubbo-compatible.json
new file mode 100644
index 0000000..bb651bd
--- /dev/null
+++ b/zh-cn/blog/dubbo-compatible.json
@@ -0,0 +1,7 @@
+{
+  "filename": "dubbo-compatible.md",
+  "__html": "<h1>Dubbo 2.7.x repackage后的兼容实现方案</h1>\n<p>Dubbo至加入Apache孵化器以来,一个很强的诉求就是需要rename groupId和package name,这两项工作在项目毕业前需要完成。其中rename package相对来说复杂一些,除了要修改所有类的包名为<code>org.apache.dubbo</code>外,更多的是需要考虑如何老版本的兼容性。</p>\n<p>常见的兼容性包括但不限于以下几种情况:</p>\n<ul>\n<li>用户API\n<ul>\n<li>编程API</li>\n<li>Spring注解</li>\n</ul>\n</li>\n<li>扩展SPI\n<ul>\n<li>扩展Filter</li>\n</ul>\n</li>\n</ul>\n<p>2.7.x里就是通过增加了一个新的模块<code>dubbo-compatible</code>来解决以上兼容性问题。</p>\n<h2>编程使用API</h2>\n<p>编程使用API是最直接最原始的使用方式,其他方 [...]
+  "title": "Dubbo 2.7.x repackage后的兼容实现方案",
+  "keywords": "Dubbo, repackage, 兼容",
+  "description": "本文简单描述了2.7.x repackage后对老版本的兼容性实现方案。"
+}
\ No newline at end of file
diff --git a/zh-cn/blog/dubbo-contribue-to-opensource.html b/zh-cn/blog/dubbo-contribue-to-opensource.html
index b1922a9..69e7874 100644
--- a/zh-cn/blog/dubbo-contribue-to-opensource.html
+++ b/zh-cn/blog/dubbo-contribue-to-opensource.html
@@ -12,8 +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="-1828827822"><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 [...]
-<hr>
+	<div id="root"><div class="blog-detail-page" data-reactroot="" data-reactid="1" data-react-checksum="-763474956"><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>Github 上有众多优秀的开源项目,大多数 IT 从业者将其当做了予取予求的工具库,遇到什么需求,先去 Github 搜一把,但有没有想过有一天自己也可以给开源事业做一些贡献呢?本文将会以 incubator-dubbo 项目为例,向你阐释,给开源项目做贡献并不是一件难事。</p>
 <h2>1 为何要给开源贡献力量</h2>
 <p>为开源项目做贡献得到的收益是多方面的,为了让你有足够的信心加入到开源项目中,我在文章最开始列举出它的诸多好处。</p>
diff --git a/zh-cn/blog/dubbo-contribue-to-opensource.json b/zh-cn/blog/dubbo-contribue-to-opensource.json
index 533664c..e0d8f69 100644
--- a/zh-cn/blog/dubbo-contribue-to-opensource.json
+++ b/zh-cn/blog/dubbo-contribue-to-opensource.json
@@ -1,6 +1,6 @@
 {
   "filename": "dubbo-contribue-to-opensource.md",
-  "__html": "<h1>以Dubbo为例,聊聊如何向开源项目做贡献</h1>\n<hr>\n<p>Github 上有众多优秀的开源项目,大多数 IT 从业者将其当做了予取予求的工具库,遇到什么需求,先去 Github 搜一把,但有没有想过有一天自己也可以给开源事业做一些贡献呢?本文将会以 incubator-dubbo 项目为例,向你阐释,给开源项目做贡献并不是一件难事。</p>\n<h2>1 为何要给开源贡献力量</h2>\n<p>为开源项目做贡献得到的收益是多方面的,为了让你有足够的信心加入到开源项目中,我在文章最开始列举出它的诸多好处。</p>\n<h3>1.1 巩固技能</h3>\n<p>无论你是提交代码,撰写文档,提交 Issue,组织活动,当你切身参与到一个开源项目中,相关的技能都会得到历练,并且在开源项目中找到自己的位置。一方面,日常工作中我们中的大多数人接触到的是业务场景,并没有太多机会接触到基�
 ��架构组件,开源项目为我们提供了一个平台,在这里,你可以尽情挑选自己熟悉的项目为它添砖加瓦(以 Dubbo 为例,并不是所有 IT 公司都有能力自研服务 [...]
+  "__html": "<h1>以Dubbo为例,聊聊如何向开源项目做贡献</h1>\n<p>Github 上有众多优秀的开源项目,大多数 IT 从业者将其当做了予取予求的工具库,遇到什么需求,先去 Github 搜一把,但有没有想过有一天自己也可以给开源事业做一些贡献呢?本文将会以 incubator-dubbo 项目为例,向你阐释,给开源项目做贡献并不是一件难事。</p>\n<h2>1 为何要给开源贡献力量</h2>\n<p>为开源项目做贡献得到的收益是多方面的,为了让你有足够的信心加入到开源项目中,我在文章最开始列举出它的诸多好处。</p>\n<h3>1.1 巩固技能</h3>\n<p>无论你是提交代码,撰写文档,提交 Issue,组织活动,当你切身参与到一个开源项目中,相关的技能都会得到历练,并且在开源项目中找到自己的位置。一方面,日常工作中我们中的大多数人接触到的是业务场景,并没有太多机会接触到基础架�
 ��组件,开源项目为我们提供了一个平台,在这里,你可以尽情挑选自己熟悉的项目为它添砖加瓦(以 Dubbo 为例,并不是所有 IT 公司都有能力自研服务治理框架); [...]
   "title": "以Dubbo为例,聊聊如何向开源项目做贡献",
   "keywords": "Dubbo, opensource",
   "description": "本文将会以 incubator-dubbo 项目为例向你阐释,给开源项目做贡献并不是一件难事"
diff --git a/zh-cn/blog/dubbo-meetup-chengdu.html b/zh-cn/blog/dubbo-meetup-chengdu.html
index f5531f5..47f6fe1 100644
--- a/zh-cn/blog/dubbo-meetup-chengdu.html
+++ b/zh-cn/blog/dubbo-meetup-chengdu.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="-570890930"><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 [...]
+	<div id="root"><div class="blog-detail-page" data-reactroot="" data-reactid="1" data-react-checksum="-857807540"><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>Aliware Open Source•成都站-Apache Dubbo开发者沙龙将于8月26日(周日)在成都高新区天府五街200号菁蓉国际广场8号楼2楼会议厅举办,技术GG们的思想盛宴,干货与福利一个都不会少。</p>
 <p>报名链接:<a href="http://www.huodongxing.com/event/7453091088400">http://www.huodongxing.com/event/7453091088400</a></p>
 <img src="../../img/blog/dubbo-chengdu-meetup-img.jpg"/>
diff --git a/zh-cn/blog/dubbo-meetup-chengdu.json b/zh-cn/blog/dubbo-meetup-chengdu.json
index 74e178e..c0eb249 100644
--- a/zh-cn/blog/dubbo-meetup-chengdu.json
+++ b/zh-cn/blog/dubbo-meetup-chengdu.json
@@ -1,6 +1,6 @@
 {
   "filename": "dubbo-meetup-chengdu.md",
-  "__html": "<h2>第四届Dubbo开发者沙龙将于8月26日在成都举行</h2>\n<p>Aliware Open Source•成都站-Apache Dubbo开发者沙龙将于8月26日(周日)在成都高新区天府五街200号菁蓉国际广场8号楼2楼会议厅举办,技术GG们的思想盛宴,干货与福利一个都不会少。</p>\n<p>报名链接:<a href=\"http://www.huodongxing.com/event/7453091088400\">http://www.huodongxing.com/event/7453091088400</a></p>\n<img src=\"../../img/blog/dubbo-chengdu-meetup-img.jpg\"/>\n",
+  "__html": "<h1>第四届Dubbo开发者沙龙将于8月26日在成都举行</h1>\n<p>Aliware Open Source•成都站-Apache Dubbo开发者沙龙将于8月26日(周日)在成都高新区天府五街200号菁蓉国际广场8号楼2楼会议厅举办,技术GG们的思想盛宴,干货与福利一个都不会少。</p>\n<p>报名链接:<a href=\"http://www.huodongxing.com/event/7453091088400\">http://www.huodongxing.com/event/7453091088400</a></p>\n<img src=\"../../img/blog/dubbo-chengdu-meetup-img.jpg\"/>\n",
   "title": "第四届Dubbo开发者沙龙将于8月26日在成都举行",
   "keywords": "Dubbo, 成都, meetup",
   "description": "第四届Dubbo开发者沙龙将于8月26日在成都举行。"
diff --git a/zh-cn/blog/dubbo-meetup-shanghai-jun-23rd-2018.html b/zh-cn/blog/dubbo-meetup-shanghai-jun-23rd-2018.html
index d4149d0..434e2f3 100644
--- a/zh-cn/blog/dubbo-meetup-shanghai-jun-23rd-2018.html
+++ b/zh-cn/blog/dubbo-meetup-shanghai-jun-23rd-2018.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="545233117"><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-tog [...]
+	<div id="root"><div class="blog-detail-page" data-reactroot="" data-reactid="1" data-react-checksum="184588507"><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-tog [...]
 <p>第二届Dubbo开发者沙龙在上海成功举办,超过700位开发者报名,现场参与人数300+,通过阿里云天池、云栖社区、大咖说引导线上直播观看次数10000+</p>
 <p>分享嘉宾及PPT:</p>
 <ul>
diff --git a/zh-cn/blog/dubbo-meetup-shanghai-jun-23rd-2018.json b/zh-cn/blog/dubbo-meetup-shanghai-jun-23rd-2018.json
index aecba96..2d52fbb 100644
--- a/zh-cn/blog/dubbo-meetup-shanghai-jun-23rd-2018.json
+++ b/zh-cn/blog/dubbo-meetup-shanghai-jun-23rd-2018.json
@@ -1,4 +1,4 @@
 {
   "filename": "dubbo-meetup-shanghai-jun-23rd-2018.md",
-  "__html": "<h2>第二届Dubbo开发者沙龙在上海成功举办</h2>\n<p>第二届Dubbo开发者沙龙在上海成功举办,超过700位开发者报名,现场参与人数300+,通过阿里云天池、云栖社区、大咖说引导线上直播观看次数10000+</p>\n<p>分享嘉宾及PPT:</p>\n<ul>\n<li>朱勇: Dubbo开源现状与未来规划 (中文) <a href=\"https://github.com/dubbo/awesome-dubbo/blob/master/slides/meetup/201806%40Shanghai/dubbo-status-and-roadmap.pdf\">slides</a></li>\n<li>小马哥: Dubbo Cloud Native 之路的实践与思考 (中文) <a href=\"https://github.com/dubbo/awesome-dubbo/blob/master/slides/meetup/201806%40Shanghai/dubbo-cloud-native-practices-and-th [...]
+  "__html": "<h1>第二届Dubbo开发者沙龙在上海成功举办</h1>\n<p>第二届Dubbo开发者沙龙在上海成功举办,超过700位开发者报名,现场参与人数300+,通过阿里云天池、云栖社区、大咖说引导线上直播观看次数10000+</p>\n<p>分享嘉宾及PPT:</p>\n<ul>\n<li>朱勇: Dubbo开源现状与未来规划 (中文) <a href=\"https://github.com/dubbo/awesome-dubbo/blob/master/slides/meetup/201806%40Shanghai/dubbo-status-and-roadmap.pdf\">slides</a></li>\n<li>小马哥: Dubbo Cloud Native 之路的实践与思考 (中文) <a href=\"https://github.com/dubbo/awesome-dubbo/blob/master/slides/meetup/201806%40Shanghai/dubbo-cloud-native-practices-and-th [...]
 }
\ No newline at end of file
diff --git a/zh-cn/blog/dubbo-meetup-shenzhen.html b/zh-cn/blog/dubbo-meetup-shenzhen.html
index fefabf7..5b2d061 100644
--- a/zh-cn/blog/dubbo-meetup-shenzhen.html
+++ b/zh-cn/blog/dubbo-meetup-shenzhen.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="-550964757"><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 [...]
+	<div id="root"><div class="blog-detail-page" data-reactroot="" data-reactid="1" data-react-checksum="-825626135"><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开发者沙龙在深圳成功举办,超过2000位开发者报名,现场参与人数700+,通过阿里云天池、云栖社区、大咖说引导线上直播观看次数17000+</p>
 <p>分享嘉宾</p>
 <ul>
diff --git a/zh-cn/blog/dubbo-meetup-shenzhen.json b/zh-cn/blog/dubbo-meetup-shenzhen.json
index bbdddcd..f5b13cb 100644
--- a/zh-cn/blog/dubbo-meetup-shenzhen.json
+++ b/zh-cn/blog/dubbo-meetup-shenzhen.json
@@ -1,4 +1,4 @@
 {
   "filename": "dubbo-meetup-shenzhen.md",
-  "__html": "<h2>第三届Dubbo开发者沙龙在深圳成功举办</h2>\n<p>第三届Dubbo开发者沙龙在深圳成功举办,超过2000位开发者报名,现场参与人数700+,通过阿里云天池、云栖社区、大咖说引导线上直播观看次数17000+</p>\n<p>分享嘉宾</p>\n<ul>\n<li>陈志轩: Dubbo开源现状和2.7规划</li>\n<li>康彬: 乐信集团的微服务化之路</li>\n<li>林佳梁: Sentinel——企业用户的全方位流量哨兵</li>\n</ul>\n"
+  "__html": "<h1>第三届Dubbo开发者沙龙在深圳成功举办</h1>\n<p>第三届Dubbo开发者沙龙在深圳成功举办,超过2000位开发者报名,现场参与人数700+,通过阿里云天池、云栖社区、大咖说引导线上直播观看次数17000+</p>\n<p>分享嘉宾</p>\n<ul>\n<li>陈志轩: Dubbo开源现状和2.7规划</li>\n<li>康彬: 乐信集团的微服务化之路</li>\n<li>林佳梁: Sentinel——企业用户的全方位流量哨兵</li>\n</ul>\n"
 }
\ No newline at end of file
diff --git a/zh-cn/blog/index.html b/zh-cn/blog/index.html
index 97200b2..9482c53 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="1174953479"><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 [...]
+	<div id="root"><div class="blog-list-page" data-reactroot="" data-reactid="1" data-react-checksum="-1324957944"><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-tog [...]
 	<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/zh-cn/blog/introduction-to-dubbo-spi.html b/zh-cn/blog/introduction-to-dubbo-spi.html
index 59f902e..631742c 100644
--- a/zh-cn/blog/introduction-to-dubbo-spi.html
+++ b/zh-cn/blog/introduction-to-dubbo-spi.html
@@ -12,8 +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="-307969909"><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 [...]
-<hr>
+	<div id="root"><div class="blog-detail-page" data-reactroot="" data-reactid="1" data-react-checksum="1372176173"><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 [...]
 <h2>1. Dubbo的扩展机制</h2>
 <p>在Dubbo的官网上,Dubbo描述自己是一个高性能的RPC框架。今天我想聊聊Dubbo的另一个很棒的特性, 就是它的可扩展性。
 如同罗马不是一天建成的,任何系统都一定是从小系统不断发展成为大系统的,想要从一开始就把系统设计的足够完善是不可能的,相反的,我们应该关注当下的需求,然后再不断地对系统进行迭代。在代码层面,要求我们适当的对关注点进行抽象和隔离,在软件不断添加功能和特性时,依然能保持良好的结构和可维护性,同时允许第三方开发者对其功能进行扩展。在某些时候,软件设计者对扩展性的追求甚至超过了性能。</p>
diff --git a/zh-cn/blog/introduction-to-dubbo-spi.json b/zh-cn/blog/introduction-to-dubbo-spi.json
index 3306599..19d6f5c 100644
--- a/zh-cn/blog/introduction-to-dubbo-spi.json
+++ b/zh-cn/blog/introduction-to-dubbo-spi.json
@@ -1,6 +1,6 @@
 {
   "filename": "introduction-to-dubbo-spi.md",
-  "__html": "<h1>Dubbo可扩展机制实战</h1>\n<hr>\n<h2>1. Dubbo的扩展机制</h2>\n<p>在Dubbo的官网上,Dubbo描述自己是一个高性能的RPC框架。今天我想聊聊Dubbo的另一个很棒的特性, 就是它的可扩展性。\n如同罗马不是一天建成的,任何系统都一定是从小系统不断发展成为大系统的,想要从一开始就把系统设计的足够完善是不可能的,相反的,我们应该关注当下的需求,然后再不断地对系统进行迭代。在代码层面,要求我们适当的对关注点进行抽象和隔离,在软件不断添加功能和特性时,依然能保持良好的结构和可维护性,同时允许第三方开发者对其功能进行扩展。在某些时候,软件设计者对扩展性的追求甚至超过了性能。</p>\n<p>在谈到软件设计时,可扩展性一直被谈起,那到底什么才是可扩展性,什么样的框架才算有良好的可扩展性呢?它必须要做到以下两点
 :</p>\n<ol>\n<li>作为框架的维护者,在添加一个新功能时,只需要添加一些新代码,而不用大量的修改现有的代码,即符合开闭原则。</li>\n<li>作为框架的使用者,在添加一个新功能时,不需 [...]
+  "__html": "<h1>Dubbo可扩展机制实战</h1>\n<h2>1. Dubbo的扩展机制</h2>\n<p>在Dubbo的官网上,Dubbo描述自己是一个高性能的RPC框架。今天我想聊聊Dubbo的另一个很棒的特性, 就是它的可扩展性。\n如同罗马不是一天建成的,任何系统都一定是从小系统不断发展成为大系统的,想要从一开始就把系统设计的足够完善是不可能的,相反的,我们应该关注当下的需求,然后再不断地对系统进行迭代。在代码层面,要求我们适当的对关注点进行抽象和隔离,在软件不断添加功能和特性时,依然能保持良好的结构和可维护性,同时允许第三方开发者对其功能进行扩展。在某些时候,软件设计者对扩展性的追求甚至超过了性能。</p>\n<p>在谈到软件设计时,可扩展性一直被谈起,那到底什么才是可扩展性,什么样的框架才算有良好的可扩展性呢?它必须要做到以下两点:</p>\
 n<ol>\n<li>作为框架的维护者,在添加一个新功能时,只需要添加一些新代码,而不用大量的修改现有的代码,即符合开闭原则。</li>\n<li>作为框架的使用者,在添加一个新功能时,不需要去修改框架 [...]
   "title": "Dubbo可扩展机制实战",
   "keywords": "Dubbo, SPI",
   "description": "本文介绍了Dubbo框架的核心,SPI扩展机制。"
diff --git a/zh-cn/blog/optimization-branch-prediction.html b/zh-cn/blog/optimization-branch-prediction.html
index a36cf20..cdbc91b 100644
--- a/zh-cn/blog/optimization-branch-prediction.html
+++ b/zh-cn/blog/optimization-branch-prediction.html
@@ -12,8 +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="-1756630036"><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 [...]
-<hr>
+	<div id="root"><div class="blog-detail-page" data-reactroot="" data-reactid="1" data-react-checksum="814740110"><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-tog [...]
 <h2>分支预测</h2>
 <p>在stackoverflow上有一个非常有名的问题:<a href="https://stackoverflow.com/questions/11227809/why-is-it-faster-to-process-a-sorted-array-than-an-unsorted-array">为什么处理有序数组要比非有序数组快?</a>,可见分支预测对代码运行效率有非常大的影响。</p>
 <p>现代CPU都支持分支预测(branch prediction)和指令流水线(instruction pipeline),这两个结合可以极大提高CPU效率。对于像简单的if跳转,CPU是可以比较好地做分支预测的。但是对于switch跳转,CPU则没有太多的办法。switch本质上是据索引,从地址数组里取地址再跳转。</p>
diff --git a/zh-cn/blog/optimization-branch-prediction.json b/zh-cn/blog/optimization-branch-prediction.json
index f415008..05ea9f9 100644
--- a/zh-cn/blog/optimization-branch-prediction.json
+++ b/zh-cn/blog/optimization-branch-prediction.json
@@ -1,5 +1,5 @@
 {
   "filename": "optimization-branch-prediction.md",
-  "__html": "<h1>优化技巧:提前if判断帮助CPU分支预测</h1>\n<hr>\n<h2>分支预测</h2>\n<p>在stackoverflow上有一个非常有名的问题:<a href=\"https://stackoverflow.com/questions/11227809/why-is-it-faster-to-process-a-sorted-array-than-an-unsorted-array\">为什么处理有序数组要比非有序数组快?</a>,可见分支预测对代码运行效率有非常大的影响。</p>\n<p>现代CPU都支持分支预测(branch prediction)和指令流水线(instruction pipeline),这两个结合可以极大提高CPU效率。对于像简单的if跳转,CPU是可以比较好地做分支预测的。但是对于switch跳转,CPU则没有太多的办法。switch本质上是据索引,从地址数组里取地址再跳转。</p>\n<p>要提高代码执行效率,一个重要的原则就是尽量避免CPU把流水线清空,那么提高分支预测的成功率就非常重要。</p>\ [...]
+  "__html": "<h1>优化技巧:提前if判断帮助CPU分支预测</h1>\n<h2>分支预测</h2>\n<p>在stackoverflow上有一个非常有名的问题:<a href=\"https://stackoverflow.com/questions/11227809/why-is-it-faster-to-process-a-sorted-array-than-an-unsorted-array\">为什么处理有序数组要比非有序数组快?</a>,可见分支预测对代码运行效率有非常大的影响。</p>\n<p>现代CPU都支持分支预测(branch prediction)和指令流水线(instruction pipeline),这两个结合可以极大提高CPU效率。对于像简单的if跳转,CPU是可以比较好地做分支预测的。但是对于switch跳转,CPU则没有太多的办法。switch本质上是据索引,从地址数组里取地址再跳转。</p>\n<p>要提高代码执行效率,一个重要的原则就是尽量避免CPU把流水线清空,那么提高分支预测的成功率就非常重要。</p>\n<p>那么 [...]
   "title": "提前if判断帮助CPU分支预测"
 }
\ No newline at end of file