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

iluo 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 03be83b  rebuild website
03be83b is described below

commit 03be83bb5bb7bf51990301323874ac0cd918f00d
Author: Ian Luo <ian....@gmail.com>
AuthorDate: Fri May 24 13:24:13 2019 +0800

    rebuild website
---
 build/blog.js                                      |   6 +-
 build/blogDetail.js                                |   6 +-
 build/community.js                                 |   6 +-
 build/documentation.js                             |   6 +-
 build/home.js                                      |   6 +-
 en-us/blog/dubbo2-js.html                          |   2 +-
 en-us/blog/dubbo2-js.json                          |   2 +-
 en-us/blog/gsoc-2018.html                          |   6 +-
 en-us/blog/gsoc-2018.json                          |   6 +-
 en-us/blog/prepare-an-apache-release.html          |   5 +-
 en-us/blog/prepare-an-apache-release.json          |   5 +-
 en-us/docs/user/demos/local-call.html              |   2 +-
 en-us/docs/user/demos/local-call.json              |   2 +-
 en-us/docs/user/references/registry/zookeeper.html |   1 +
 en-us/docs/user/references/registry/zookeeper.json |   2 +-
 md_json/blog.json                                  |  45 ++-
 .../blog/build-new-docker-image-in-dockerhub.html  |  73 ++++
 .../blog/build-new-docker-image-in-dockerhub.json  |  10 +
 zh-cn/blog/dubbo-contribute-to-opensource.html     |   2 +-
 zh-cn/blog/dubbo-contribute-to-opensource.json     |   2 +-
 zh-cn/blog/dubbo-network-interfaces.html           | 406 +++++++++++++++++++++
 zh-cn/blog/dubbo-network-interfaces.json           |  10 +
 zh-cn/blog/dubbo-registry-nacos-integration.html   |   8 +-
 zh-cn/blog/dubbo-registry-nacos-integration.json   |   2 +-
 zh-cn/blog/gsoc-2018.html                          |  34 ++
 zh-cn/blog/gsoc-2018.json                          |  10 +
 zh-cn/blog/index.html                              |   2 +-
 zh-cn/blog/prepare-an-apache-release.html          |   2 +-
 zh-cn/blog/prepare-an-apache-release.json          |   3 +-
 zh-cn/docs/user/references/registry/zookeeper.html |   1 +
 zh-cn/docs/user/references/registry/zookeeper.json |   2 +-
 31 files changed, 630 insertions(+), 45 deletions(-)

diff --git a/build/blog.js b/build/blog.js
index 2093a47..638de8e 100644
--- a/build/blog.js
+++ b/build/blog.js
@@ -1,6 +1,6 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var 
o=n[r]={i:r,l:!1,exports:{}};return 
e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var 
n={};t.m=e,t.c=n,t.i=function(e){return 
e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var
 n=e&&e.__esModule?function(){return e.default}:function(){return e};return 
t.d(n,"a",n),n},t.o=function(e,t){return 
Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=80) [...]
-  Copyright (c) 2016 Jed Watson.
+!function(e){function t(r){if(n[r])return n[r].exports;var 
o=n[r]={i:r,l:!1,exports:{}};return 
e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var 
n={};t.m=e,t.c=n,t.i=function(e){return 
e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var
 n=e&&e.__esModule?function(){return e.default}:function(){return e};return 
t.d(n,"a",n),n},t.o=function(e,t){return 
Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=78) [...]
+  Copyright (c) 2017 Jed Watson.
   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))e.push(n.apply(null,r));else if("object"===o)for(var a in 
r)i.call(r,a)&&r[a]&&e.push(a)}}return e.join(" ")}var i={}.hasOwnProperty;void 
0!==e&&e.exports?e.exports=n:(r=[],void 0!==(o=function(){return 
n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";function 
r(e,t,r){var o=r.configurable,u= [...]
\ 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/build/blogDetail.js b/build/blogDetail.js
index d692035..0b83413 100644
--- a/build/blogDetail.js
+++ b/build/blogDetail.js
@@ -1,6 +1,6 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var 
o=n[r]={i:r,l:!1,exports:{}};return 
e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var 
n={};t.m=e,t.c=n,t.i=function(e){return 
e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var
 n=e&&e.__esModule?function(){return e.default}:function(){return e};return 
t.d(n,"a",n),n},t.o=function(e,t){return 
Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=81) [...]
-  Copyright (c) 2016 Jed Watson.
+!function(e){function t(r){if(n[r])return n[r].exports;var 
o=n[r]={i:r,l:!1,exports:{}};return 
e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var 
n={};t.m=e,t.c=n,t.i=function(e){return 
e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var
 n=e&&e.__esModule?function(){return e.default}:function(){return e};return 
t.d(n,"a",n),n},t.o=function(e,t){return 
Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=79) [...]
+  Copyright (c) 2017 Jed Watson.
   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))e.push(n.apply(null,r));else if("object"===o)for(var a in 
r)i.call(r,a)&&r[a]&&e.push(a)}}return e.join(" ")}var i={}.hasOwnProperty;void 
0!==e&&e.exports?e.exports=n:(r=[],void 0!==(o=function(){return 
n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";function 
r(e,t,r){var o=r.configurable,u= [...]
\ 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/build/community.js b/build/community.js
index e767bdc..10d9790 100644
--- a/build/community.js
+++ b/build/community.js
@@ -1,6 +1,6 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var 
o=n[r]={i:r,l:!1,exports:{}};return 
e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var 
n={};t.m=e,t.c=n,t.i=function(e){return 
e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var
 n=e&&e.__esModule?function(){return e.default}:function(){return e};return 
t.d(n,"a",n),n},t.o=function(e,t){return 
Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=82) [...]
-  Copyright (c) 2016 Jed Watson.
+!function(e){function t(r){if(n[r])return n[r].exports;var 
o=n[r]={i:r,l:!1,exports:{}};return 
e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var 
n={};t.m=e,t.c=n,t.i=function(e){return 
e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var
 n=e&&e.__esModule?function(){return e.default}:function(){return e};return 
t.d(n,"a",n),n},t.o=function(e,t){return 
Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=80) [...]
+  Copyright (c) 2017 Jed Watson.
   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))e.push(n.apply(null,r));else if("object"===o)for(var a in 
r)i.call(r,a)&&r[a]&&e.push(a)}}return e.join(" ")}var i={}.hasOwnProperty;void 
0!==e&&e.exports?e.exports=n:(r=[],void 0!==(o=function(){return 
n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";function 
r(e,t,r){var o=r.configurable,l= [...]
\ 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 l in r)i.call(r,l)&&r[l]&&e.push(l)}}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/build/documentation.js b/build/documentation.js
index e6ef1ad..d70b7df 100644
--- a/build/documentation.js
+++ b/build/documentation.js
@@ -1,6 +1,6 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var 
o=n[r]={i:r,l:!1,exports:{}};return 
e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var 
n={};t.m=e,t.c=n,t.i=function(e){return 
e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var
 n=e&&e.__esModule?function(){return e.default}:function(){return e};return 
t.d(n,"a",n),n},t.o=function(e,t){return 
Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=83) [...]
-  Copyright (c) 2016 Jed Watson.
+!function(e){function t(r){if(n[r])return n[r].exports;var 
o=n[r]={i:r,l:!1,exports:{}};return 
e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var 
n={};t.m=e,t.c=n,t.i=function(e){return 
e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var
 n=e&&e.__esModule?function(){return e.default}:function(){return e};return 
t.d(n,"a",n),n},t.o=function(e,t){return 
Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=81) [...]
+  Copyright (c) 2017 Jed Watson.
   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))e.push(n.apply(null,r));else if("object"===o)for(var l in 
r)i.call(r,l)&&r[l]&&e.push(l)}}return e.join(" ")}var i={}.hasOwnProperty;void 
0!==e&&e.exports?e.exports=n:(r=[],void 0!==(o=function(){return 
n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";function 
r(e,t,r){var o=r.configurable,s= [...]
\ 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 l=n.apply(null,r);l&&e.push(l)}else 
if("object"===o)for(var s in r)i.call(r,s)&&r[s]&&e.push(s)}}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/build/home.js b/build/home.js
index add8b7d..92937bf 100644
--- a/build/home.js
+++ b/build/home.js
@@ -1,6 +1,6 @@
-!function(e){function t(r){if(n[r])return n[r].exports;var 
o=n[r]={i:r,l:!1,exports:{}};return 
e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var 
n={};t.m=e,t.c=n,t.i=function(e){return 
e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var
 n=e&&e.__esModule?function(){return e.default}:function(){return e};return 
t.d(n,"a",n),n},t.o=function(e,t){return 
Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=84) [...]
-  Copyright (c) 2016 Jed Watson.
+!function(e){function t(r){if(n[r])return n[r].exports;var 
o=n[r]={i:r,l:!1,exports:{}};return 
e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var 
n={};t.m=e,t.c=n,t.i=function(e){return 
e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var
 n=e&&e.__esModule?function(){return e.default}:function(){return e};return 
t.d(n,"a",n),n},t.o=function(e,t){return 
Object.prototype.hasOwnProperty.call(e,t)},t.p="/build/",t(t.s=82) [...]
+  Copyright (c) 2017 Jed Watson.
   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))e.push(n.apply(null,r));else if("object"===o)for(var a in 
r)i.call(r,a)&&r[a]&&e.push(a)}}return e.join(" ")}var i={}.hasOwnProperty;void 
0!==e&&e.exports?e.exports=n:(r=[],void 0!==(o=function(){return 
n}.apply(t,r))&&(e.exports=o))}()},function(e,t,n){"use strict";function 
r(e,t,r){var o=r.configurable,u= [...]
\ 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 i=n.apply(null,r);i&&e.push(i)}else 
if("object"===o)for(var u in r)a.call(r,u)&&r[u]&&e.push(u)}}return e.join(" 
")}var a={}.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/dubbo2-js.html b/en-us/blog/dubbo2-js.html
index c86ffe0..ee5a31f 100644
--- a/en-us/blog/dubbo2-js.html
+++ b/en-us/blog/dubbo2-js.html
@@ -4,7 +4,7 @@
 <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, 跨语言, Node, NodeJS, js" />
+       <meta name="keywords" content="Dubbo, Cross-language, Node, NodeJS, js" 
/>
        <meta name="description" content="This article introduces how to use 
Dubbo.js to implement cross-language calls." />
        <!-- 网页标签标题 -->
        <title>Implementation of cross-language calls by Dubbo2.js</title>
diff --git a/en-us/blog/dubbo2-js.json b/en-us/blog/dubbo2-js.json
index a56bfe6..78021db 100644
--- a/en-us/blog/dubbo2-js.json
+++ b/en-us/blog/dubbo2-js.json
@@ -4,7 +4,7 @@
   "link": "/en-us/blog/dubbo2-js.html",
   "meta": {
     "title": "Implementation of cross-language calls by Dubbo2.js",
-    "keywords": "Dubbo, 跨语言, Node, NodeJS, js",
+    "keywords": "Dubbo, Cross-language, Node, NodeJS, js",
     "description": "This article introduces how to use Dubbo.js to implement 
cross-language calls."
   }
 }
\ No newline at end of file
diff --git a/en-us/blog/gsoc-2018.html b/en-us/blog/gsoc-2018.html
index 639a2b8..5938ae1 100644
--- a/en-us/blog/gsoc-2018.html
+++ b/en-us/blog/gsoc-2018.html
@@ -4,10 +4,10 @@
 <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="gsoc-2018" />
-       <meta name="description" content="gsoc-2018" />
+       <meta name="keywords" content="Dubbo, GSoC" />
+       <meta name="description" content="The GSoC(Google Summer of Code) 2018 
projects has been announced" />
        <!-- 网页标签标题 -->
-       <title>gsoc-2018</title>
+       <title>GSoC 2018</title>
        <link rel="shortcut icon" href="/img/dubbo.ico"/>
        <link rel="stylesheet" href="/build/blogDetail.css" />
 </head>
diff --git a/en-us/blog/gsoc-2018.json b/en-us/blog/gsoc-2018.json
index 851a652..dfc7dcb 100644
--- a/en-us/blog/gsoc-2018.json
+++ b/en-us/blog/gsoc-2018.json
@@ -2,5 +2,9 @@
   "filename": "gsoc-2018.md",
   "__html": "<h2>The GSoC(Google Summer of Code) 2018 projects has been 
announced</h2>\n<p>The GSoC(Google Summer of Code) 2018 projects has been 
announced, Raghu Reddy's project &quot;Extending Serialization protocols 
support for Apache Dubbo&quot; has been <a 
href=\"https://summerofcode.withgoogle.com/projects/#4747840161579008\";>accepted</a>!
 Congratulations!</p>\n",
   "link": "/en-us/blog/gsoc-2018.html",
-  "meta": {}
+  "meta": {
+    "title": "GSoC 2018",
+    "keywords": "Dubbo, GSoC",
+    "description": "The GSoC(Google Summer of Code) 2018 projects has been 
announced"
+  }
 }
\ No newline at end of file
diff --git a/en-us/blog/prepare-an-apache-release.html 
b/en-us/blog/prepare-an-apache-release.html
index 60a2e8f..ff916db 100644
--- a/en-us/blog/prepare-an-apache-release.html
+++ b/en-us/blog/prepare-an-apache-release.html
@@ -5,14 +5,15 @@
        <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, Apache, Release" />
-       <meta name="description" content="prepare-an-apache-release" />
+       <meta name="description" content="This article introduces how to the 
Apache publish content and process" />
        <!-- 网页标签标题 -->
        <title>Understanding the Apache Release Cycle</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=""><header 
class="header-container header-container-normal"><div class="header-body"><a 
href="/en-us/index.html"><img class="logo" 
src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span 
class="icon-search"></span></div><span class="language-switch 
language-switch-normal">中</span><div class="header-menu"><img 
class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item 
menu-item-normal"><a hr [...]
+       <div id="root"><div class="blog-detail-page" data-reactroot=""><header 
class="header-container header-container-normal"><div class="header-body"><a 
href="/en-us/index.html"><img class="logo" 
src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span 
class="icon-search"></span></div><span class="language-switch 
language-switch-normal">中</span><div class="header-menu"><img 
class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item 
menu-item-normal"><a hr [...]
+<h2>Understanding the Apache Release Cycle</h2>
 <p>In general, Source Release is the key and the required content of Apache. 
But Binary Release is optional, Dubbo can choose whether to release binary 
packages to the Apache repository or to the Maven central repository.</p>
 <p>Please refer to the following links for more information on ASF's release 
guide:</p>
 <ul>
diff --git a/en-us/blog/prepare-an-apache-release.json 
b/en-us/blog/prepare-an-apache-release.json
index f2484e2..29fe018 100644
--- a/en-us/blog/prepare-an-apache-release.json
+++ b/en-us/blog/prepare-an-apache-release.json
@@ -1,9 +1,10 @@
 {
   "filename": "prepare-an-apache-release.md",
-  "__html": "<h2>Understanding the Apache Release Cycle</h2>\n<p>In general, 
Source Release is the key and the required content of Apache. But Binary 
Release is optional, Dubbo can choose whether to release binary packages to the 
Apache repository or to the Maven central repository.</p>\n<p>Please refer to 
the following links for more information on ASF's release 
guide:</p>\n<ul>\n<li><a 
href=\"http://www.apache.org/dev/release-publishing\";>Apache Release 
Guide</a></li>\n<li><a href=\"ht [...]
+  "__html": "<h1>How to prepare an the Apache Release</h1>\n<h2>Understanding 
the Apache Release Cycle</h2>\n<p>In general, Source Release is the key and the 
required content of Apache. But Binary Release is optional, Dubbo can choose 
whether to release binary packages to the Apache repository or to the Maven 
central repository.</p>\n<p>Please refer to the following links for more 
information on ASF's release guide:</p>\n<ul>\n<li><a 
href=\"http://www.apache.org/dev/release-publishing\";> [...]
   "link": "/en-us/blog/prepare-an-apache-release.html",
   "meta": {
     "title": "Understanding the Apache Release Cycle",
-    "keywords": "Dubbo, Apache, Release"
+    "keywords": "Dubbo, Apache, Release",
+    "description": "This article introduces how to the Apache publish content 
and process"
   }
 }
\ No newline at end of file
diff --git a/en-us/docs/user/demos/local-call.html 
b/en-us/docs/user/demos/local-call.html
index 83febf5..dc7ebb8 100644
--- a/en-us/docs/user/demos/local-call.html
+++ b/en-us/docs/user/demos/local-call.html
@@ -32,7 +32,7 @@
 <pre><code class="language-xml"><span class="hljs-tag">&lt;<span 
class="hljs-name">dubbo:reference</span> <span 
class="hljs-attr">injvm</span>=<span class="hljs-string">"true"</span> <span 
class="hljs-attr">...</span>/&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">dubbo:service</span> <span 
class="hljs-attr">injvm</span>=<span class="hljs-string">"true"</span> <span 
class="hljs-attr">...</span>/&gt;</span>
 </code></pre>
-<p>Note: Dubbo is exposed locally from <code>2.2.0</code> by default. It can 
be referenced locally without any configuration. If you don't want the service 
to be exposed remotely, you only need to set the protocol to injvm in the 
provider.</p>
+<p>Note: Dubbo services are exposed locally from <code>2.2.0</code> by 
default. It can be referenced locally without any configuration. If you don't 
want the service to be exposed remotely, you only need to set the protocol to 
injvm in the provider.</p>
 <h2>Automatically exposed, local service references</h2>
 <p><code>2.2.0</code> or later, each service is exposed locally by default. 
When referring to the service, the local service is referenced by default. If 
you want to reference a remote service, you can use the following configuration 
to force a reference to a remote service.</p>
 <pre><code class="language-xml"><span class="hljs-tag">&lt;<span 
class="hljs-name">dubbo:reference</span> <span class="hljs-attr">...</span> 
<span class="hljs-attr">scope</span>=<span class="hljs-string">"remote"</span> 
/&gt;</span>
diff --git a/en-us/docs/user/demos/local-call.json 
b/en-us/docs/user/demos/local-call.json
index 9b9c264..27d35e5 100644
--- a/en-us/docs/user/demos/local-call.json
+++ b/en-us/docs/user/demos/local-call.json
@@ -1,6 +1,6 @@
 {
   "filename": "local-call.md",
-  "__html": "<h1>Local call</h1>\n<p>The local call uses the 
<code>injvm</code> protocol, a pseudo-protocol that does not turn on the port, 
does not initiate remote calls, is directly associated within the JVM, but 
executes the Dubbo Filter chain.</p>\n<h2>Configuration</h2>\n<p>Configure 
<code>injvm</code> protocol</p>\n<pre><code class=\"language-xml\"><span 
class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dubbo:protocol</span> <span 
class=\"hljs-attr\">name</span>=<span class=\"hljs-s [...]
+  "__html": "<h1>Local call</h1>\n<p>The local call uses the 
<code>injvm</code> protocol, a pseudo-protocol that does not turn on the port, 
does not initiate remote calls, is directly associated within the JVM, but 
executes the Dubbo Filter chain.</p>\n<h2>Configuration</h2>\n<p>Configure 
<code>injvm</code> protocol</p>\n<pre><code class=\"language-xml\"><span 
class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dubbo:protocol</span> <span 
class=\"hljs-attr\">name</span>=<span class=\"hljs-s [...]
   "link": "/en-us/docs/user/demos/local-call.html",
   "meta": {}
 }
\ No newline at end of file
diff --git a/en-us/docs/user/references/registry/zookeeper.html 
b/en-us/docs/user/references/registry/zookeeper.html
index a1dd51c..6e8da11 100644
--- a/en-us/docs/user/references/registry/zookeeper.html
+++ b/en-us/docs/user/references/registry/zookeeper.html
@@ -43,6 +43,7 @@
 <p>Dubbo supports two zookeeper clients: zkclient and curator:</p>
 <h3>Use zkclient</h3>
 <p>Since <code>2.2.0</code> dubbo uses zkclient by default, in order to 
improve the robustness. <a 
href="https://github.com/sgroschupf/zkclient";>zkclient</a> is a zookeeper 
client implementation open-sourced by Datameer.</p>
+<p><strong>Note: The implementation of zkclient has been removed in the 2.7.x 
version. If you want to use the zkclient client, you need to extend it 
yourself.</strong></p>
 <p>Default configuration:</p>
 <pre><code class="language-xml"><span class="hljs-tag">&lt;<span 
class="hljs-name">dubbo:registry</span> <span class="hljs-attr">...</span> 
<span class="hljs-attr">client</span>=<span 
class="hljs-string">"zkclient"</span> /&gt;</span>
 </code></pre>
diff --git a/en-us/docs/user/references/registry/zookeeper.json 
b/en-us/docs/user/references/registry/zookeeper.json
index c26d674..20deaff 100644
--- a/en-us/docs/user/references/registry/zookeeper.json
+++ b/en-us/docs/user/references/registry/zookeeper.json
@@ -1,6 +1,6 @@
 {
   "filename": "zookeeper.md",
-  "__html": "<h1>Zookeeper Registry Server</h1>\n<p><a 
href=\"http://zookeeper.apache.org\";>Zookeeper</a> is the child project of 
apache hadoop. Since it offers tree-like directory service and supports change 
notification, it's suitable to use it as dubbo's registry server. It's a 
field-proven product, therefore it's recommended to use it in the production 
environment. <sup class=\"footnote-ref\"><a href=\"#fn1\" 
id=\"fnref1\">[1]</a></sup></p>\n<p><img src=\"../../sources/images/zookeep 
[...]
+  "__html": "<h1>Zookeeper Registry Server</h1>\n<p><a 
href=\"http://zookeeper.apache.org\";>Zookeeper</a> is the child project of 
apache hadoop. Since it offers tree-like directory service and supports change 
notification, it's suitable to use it as dubbo's registry server. It's a 
field-proven product, therefore it's recommended to use it in the production 
environment. <sup class=\"footnote-ref\"><a href=\"#fn1\" 
id=\"fnref1\">[1]</a></sup></p>\n<p><img src=\"../../sources/images/zookeep 
[...]
   "link": "/en-us/docs/user/references/registry/zookeeper.html",
   "meta": {}
 }
\ No newline at end of file
diff --git a/md_json/blog.json b/md_json/blog.json
index f4433c8..7e73077 100644
--- a/md_json/blog.json
+++ b/md_json/blog.json
@@ -158,14 +158,18 @@
       "link": "/en-us/blog/dubbo2-js.html",
       "meta": {
         "title": "Implementation of cross-language calls by Dubbo2.js",
-        "keywords": "Dubbo, 跨语言, Node, NodeJS, js",
+        "keywords": "Dubbo, Cross-language, Node, NodeJS, js",
         "description": "This article introduces how to use Dubbo.js to 
implement cross-language calls."
       }
     },
     {
       "filename": "gsoc-2018.md",
       "link": "/en-us/blog/gsoc-2018.html",
-      "meta": {}
+      "meta": {
+        "title": "GSoC 2018",
+        "keywords": "Dubbo, GSoC",
+        "description": "The GSoC(Google Summer of Code) 2018 projects has been 
announced"
+      }
     },
     {
       "filename": "introduction-to-dubbo-qos.md",
@@ -208,7 +212,8 @@
       "link": "/en-us/blog/prepare-an-apache-release.html",
       "meta": {
         "title": "Understanding the Apache Release Cycle",
-        "keywords": "Dubbo, Apache, Release"
+        "keywords": "Dubbo, Apache, Release",
+        "description": "This article introduces how to the Apache publish 
content and process"
       }
     },
     {
@@ -259,6 +264,15 @@
       }
     },
     {
+      "filename": "build-new-docker-image-in-dockerhub.md",
+      "link": "/zh-cn/blog/build-new-docker-image-in-dockerhub.html",
+      "meta": {
+        "title": "在DockerHub发布Dubbo Admin镜像",
+        "keywords": "Dubbo Admin,Docker,Dockerhub",
+        "description": "本文将介绍如何在Dockerhub上发布Dubbo Admin镜像。"
+      }
+    },
+    {
       "filename": "download.md",
       "link": "/zh-cn/blog/download.html",
       "meta": {
@@ -346,8 +360,8 @@
       }
     },
     {
-      "filename": "dubbo-contribue-to-opensource.md",
-      "link": "/zh-cn/blog/dubbo-contribue-to-opensource.html",
+      "filename": "dubbo-contribute-to-opensource.md",
+      "link": "/zh-cn/blog/dubbo-contribute-to-opensource.html",
       "meta": {
         "title": "以Dubbo为例,聊聊如何向开源项目做贡献",
         "keywords": "Dubbo, opensource",
@@ -523,6 +537,15 @@
       }
     },
     {
+      "filename": "dubbo-network-interfaces.md",
+      "link": "/zh-cn/blog/dubbo-network-interfaces.html",
+      "meta": {
+        "title": "研究 Dubbo 网卡地址注册时的一点思考",
+        "keywords": "网卡地址注册",
+        "description": "研究 Dubbo 网卡地址注册时的一点思考"
+      }
+    },
+    {
       "filename": "dubbo-new-async.md",
       "link": "/zh-cn/blog/dubbo-new-async.html",
       "meta": {
@@ -597,6 +620,15 @@
       "meta": {}
     },
     {
+      "filename": "gsoc-2018.md",
+      "link": "/zh-cn/blog/gsoc-2018.html",
+      "meta": {
+        "title": "谷歌编程之夏会议上2018个项目被宣布",
+        "keywords": "Dubbo, GSoC",
+        "description": "谷歌编程之夏会议上2018个项目被宣布,Dubbo位列其中。"
+      }
+    },
+    {
       "filename": "how-to-involve-dubbo-community.md",
       "link": "/zh-cn/blog/how-to-involve-dubbo-community.html",
       "meta": {
@@ -671,7 +703,8 @@
       "link": "/zh-cn/blog/prepare-an-apache-release.html",
       "meta": {
         "title": "如何准备Apache Release",
-        "keywords": "Dubbo, Apache, Release"
+        "keywords": "Dubbo, Apache, Release",
+        "description": "本文介绍了Apache如何发布内容和流程"
       }
     },
     {
diff --git a/zh-cn/blog/build-new-docker-image-in-dockerhub.html 
b/zh-cn/blog/build-new-docker-image-in-dockerhub.html
new file mode 100644
index 0000000..79faebe
--- /dev/null
+++ b/zh-cn/blog/build-new-docker-image-in-dockerhub.html
@@ -0,0 +1,73 @@
+<!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 Admin,Docker,Dockerhub" />
+       <meta name="description" content="本文将介绍如何在Dockerhub上发布Dubbo Admin镜像。" />
+       <!-- 网页标签标题 -->
+       <title>在DockerHub发布Dubbo Admin镜像</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=""><header 
class="header-container header-container-normal"><div class="header-body"><a 
href="/zh-cn/index.html"><img class="logo" 
src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span 
class="icon-search"></span></div><span class="language-switch 
language-switch-normal">En</span><div class="header-menu"><img 
class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item 
menu-item-normal"><a h [...]
+<p>Dubbo Admin是Dubbo的服务治理中心,提供了大量日常运维所需的服务治理、配置管理等功能。</p>
+<p>Dubbo Admin同时包含了前端代码和后端代码,如果用户需要自己下载源码并编译打包,需要花费一定时间。
+特别是对于一些希望快速调研和试用Dubbo Admin的用户,这种流程的体验并不是很好。</p>
+<p>Docker是一个开源的应用容器引擎,让开发者可以打包应用以及依赖包到一个可移植的镜像中,社区对于提供Dubbo Admin镜像的呼声较高。
+Docker官方维护了一个公共仓库DockerHub,该仓库还有很多国内镜像,访问速度快,将Dubbo 
Admin镜像发布到DockerHub是一个较好的选择。</p>
+<h2>DockerHub账号申请</h2>
+<p>要在DockerHub上发布镜像,自然需要对应的账号。
+而DockerHub有两种常见账号,一种是面向个人的,一种是面向组织的。Apache在DockerHub上有一个组织账号<sup 
class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>。
+自然我们首选是发布在组织账号下。</p>
+<p>DockerHub对于组织账号的管理是基于组的,也就是一个组织账号下有多个组,每个组有不同的成员,而一个组可以管理一个或者多个镜像。</p>
+<p>所以要做的第一步就是申请权限,这个需要提一个issue给Apache Infrastructure团队,申请DockerHub的镜像仓库和组权限。
+目前镜像和组已经申请好了,只需要申请组的权限就行了,可以参考之前的申请<sup class="footnote-ref"><a href="#fn2" 
id="fnref2">[2]</a></sup>。</p>
+<p>申请完权限以后使用Apache账号登陆应该就可以看到对应的镜像和配置选项了。</p>
+<h2>添加新的构建规则</h2>
+<p>发布镜像到DockerHub有两种办法,一种是本地构建好镜像以后远程push到DockerHub,另外一种是提供Dockerfile并借助DockerHub提供的构建功能直接在DockerHub构建。
+后者明显操作性和便捷性要好很多,目前Dubbo Admin的镜像也是这样构建发布的。</p>
+<p>当Dubbo 
Admin有新版本发布以后,需要在项目的docker目录新增一个Dockerfile文件,可以参考目前0.1.0版本的Dockerfile<sup 
class="footnote-ref"><a href="#fn3" 
id="fnref3">[3]</a></sup>,其中的配置根据具体的版本可能有细微差别,但是大致上是一致的。</p>
+<p>在添加了Dockerfile之后,进入DockerHub对应的管理界面新增Build Rules</p>
+<p><img src="../../img/blog/dockerhub-build-rules.png" 
alt="dockerhub-build-rules.png | center "></p>
+<p>根据实际情况填写即可。这里需要注意两点:</p>
+<ul>
+<li>latest 版本要和最新的版本配置一致</li>
+<li>不要勾选Autobuild</li>
+</ul>
+<p>勾选Autobuild会导致每次git提交都会触发自动构建,但是由于Dubbo 
Admin不提供snapshot的Docker镜像,所以只有发布新版本的时候才需要构建发布。</p>
+<p>修改以后点Save,然后手动触发构建即可。</p>
+<h2>总结</h2>
+<p>总的来说DockerHub上发布镜像的步骤并不复杂,如果已经申请过权限的话,操作起来是很流畅的。</p>
+<p>另外DockerHub的构建是需要排队的,有时候会遇到长时间没有开始构建的情况,需要耐心等待。</p>
+<hr class="footnotes-sep">
+<section class="footnotes">
+<ol class="footnotes-list">
+<li id="fn1" class="footnote-item"><p><a 
href="https://hub.docker.com/r/apache";>https://hub.docker.com/r/apache</a> <a 
href="#fnref1" class="footnote-backref">↩︎</a></p>
+</li>
+<li id="fn2" class="footnote-item"><p><a 
href="https://issues.apache.org/jira/browse/INFRA-18167";>https://issues.apache.org/jira/browse/INFRA-18167</a>
 <a href="#fnref2" class="footnote-backref">↩︎</a></p>
+</li>
+<li id="fn3" class="footnote-item"><p><a 
href="https://github.com/apache/incubator-dubbo-admin/blob/develop/docker/0.1.0/Dockerfile";>https://github.com/apache/incubator-dubbo-admin/blob/develop/docker/0.1.0/Dockerfile</a>
 <a href="#fnref3" class="footnote-backref">↩︎</a></p>
+</li>
+</ol>
+</section>
+</section><footer class="footer-container"><div class="footer-body"><img 
src="/img/dubbo_gray.png"/><img class="apache" src="/img/apache_logo.png"/><div 
class="cols-container"><div class="col col-12"><h3></h3><p></p></div><div 
class="col col-4"><dl><dt>ASF</dt><dd><a href="http://www.apache.org"; 
target="_self">基金会</a></dd><dd><a href="http://www.apache.org/licenses/"; 
target="_self">证书</a></dd><dd><a 
href="http://www.apache.org/events/current-event"; 
target="_self">事件</a></dd><dd><a href=" [...]
+       <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/build-new-docker-image-in-dockerhub.json 
b/zh-cn/blog/build-new-docker-image-in-dockerhub.json
new file mode 100644
index 0000000..05973e2
--- /dev/null
+++ b/zh-cn/blog/build-new-docker-image-in-dockerhub.json
@@ -0,0 +1,10 @@
+{
+  "filename": "build-new-docker-image-in-dockerhub.md",
+  "__html": "<h1>在DockerHub发布Dubbo Admin镜像</h1>\n<p>Dubbo 
Admin是Dubbo的服务治理中心,提供了大量日常运维所需的服务治理、配置管理等功能。</p>\n<p>Dubbo 
Admin同时包含了前端代码和后端代码,如果用户需要自己下载源码并编译打包,需要花费一定时间。\n特别是对于一些希望快速调研和试用Dubbo 
Admin的用户,这种流程的体验并不是很好。</p>\n<p>Docker是一个开源的应用容器引擎,让开发者可以打包应用以及依赖包到一个可移植的镜像中,社区对于提供Dubbo
 Admin镜像的呼声较高。\nDocker官方维护了一个公共仓库DockerHub,该仓库还有很多国内镜像,访问速度快,将Dubbo 
Admin镜像发布到DockerHub是一个较好的选择。</p>\n<h2>DockerHub账号申请</h2>\n<p>要在DockerHub上发布镜像,自然需要对应的账号。\n而DockerHub有两种常见账号,一种是面向个人的,一种是面向组织的。Apache
 在DockerHub上有一个组织账 [...]
+  "link": "/zh-cn/blog/build-new-docker-image-in-dockerhub.html",
+  "meta": {
+    "title": "在DockerHub发布Dubbo Admin镜像",
+    "keywords": "Dubbo Admin,Docker,Dockerhub",
+    "description": "本文将介绍如何在Dockerhub上发布Dubbo Admin镜像。"
+  }
+}
\ No newline at end of file
diff --git a/zh-cn/blog/dubbo-contribute-to-opensource.html 
b/zh-cn/blog/dubbo-contribute-to-opensource.html
index a6e5451..085d49b 100644
--- a/zh-cn/blog/dubbo-contribute-to-opensource.html
+++ b/zh-cn/blog/dubbo-contribute-to-opensource.html
@@ -154,4 +154,4 @@ git merge upstream/master
                gtag('config', 'UA-112489517-1');
        </script>
 </body>
-</html>
+</html>
\ No newline at end of file
diff --git a/zh-cn/blog/dubbo-contribute-to-opensource.json 
b/zh-cn/blog/dubbo-contribute-to-opensource.json
index 9a8205f..397624a 100644
--- a/zh-cn/blog/dubbo-contribute-to-opensource.json
+++ b/zh-cn/blog/dubbo-contribute-to-opensource.json
@@ -7,4 +7,4 @@
     "keywords": "Dubbo, opensource",
     "description": "本文将会以 incubator-dubbo 项目为例向你阐释,给开源项目做贡献并不是一件难事"
   }
-}
+}
\ No newline at end of file
diff --git a/zh-cn/blog/dubbo-network-interfaces.html 
b/zh-cn/blog/dubbo-network-interfaces.html
new file mode 100644
index 0000000..da1b637
--- /dev/null
+++ b/zh-cn/blog/dubbo-network-interfaces.html
@@ -0,0 +1,406 @@
+<!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="网卡地址注册" />
+       <meta name="description" content="研究 Dubbo 网卡地址注册时的一点思考" />
+       <!-- 网页标签标题 -->
+       <title>研究 Dubbo 网卡地址注册时的一点思考</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=""><header 
class="header-container header-container-normal"><div class="header-body"><a 
href="/zh-cn/index.html"><img class="logo" 
src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span 
class="icon-search"></span></div><span class="language-switch 
language-switch-normal">En</span><div class="header-menu"><img 
class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item 
menu-item-normal"><a h [...]
+<h2>1 如何选择合适的网卡地址</h2>
+<p>可能相当一部分人还不知道我这篇文章到底要讲什么,我说个场景,大家应该就明晰了。在分布式服务调用过程中,以 Dubbo 为例,服务提供者往往需要将自身的 
IP 地址上报给注册中心,供消费者去发现。在大多数情况下 Dubbo 都可以正常工作,但如果你留意过 Dubbo 的 github 
issue,其实有不少人反馈:Dubbo Provider 注册了错误的 
IP。如果你能立刻联想到:多网卡、内外网地址共存、VPN、虚拟网卡等关键词,那我建议你一定要继续将本文看下去,因为我也想到了这些,它们都是本文所要探讨的东西!那么“如何选择合适的网卡地址”呢,Dubbo
 现有的逻辑到底算不算完备?我们不急着回答它,而是带着这些问题一起进行研究,相信到文末,其中答案,各位看官自有评说。</p>
+<h2>2 Dubbo 是怎么做的</h2>
+<p>Dubbo 获取网卡地址的逻辑在各个版本中也是千回百转,走过弯路,也做过优化,我们用最新的 2.7.2-SNAPSHOT 
版本来介绍,在看以下源码时,大家可以怀着质疑的心态去阅读,在 dubbo github 的 master 分支可以获取源码。获取 localhost 
的逻辑位于 <code>org.apache.dubbo.common.utils.NetUtils#getLocalAddress0()</code> 
之中</p>
+<pre><code class="language-java"><span class="hljs-function"><span 
class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> 
InetAddress <span class="hljs-title">getLocalAddress0</span><span 
class="hljs-params">()</span> </span>{
+    InetAddress localAddress = <span class="hljs-keyword">null</span>;
+    <span class="hljs-comment">// 首先尝试获取 /etc/hosts 中 hostname 对应的 IP</span>
+    localAddress = InetAddress.getLocalHost();
+    Optional&lt;InetAddress&gt; addressOp = toValidAddress(localAddress);
+    <span class="hljs-keyword">if</span> (addressOp.isPresent()) {
+        <span class="hljs-keyword">return</span> addressOp.get();
+    }
+
+    <span class="hljs-comment">// 没有找到适合注册的 IP,则开始轮询网卡</span>
+    Enumeration&lt;NetworkInterface&gt; interfaces = 
NetworkInterface.getNetworkInterfaces();
+    <span class="hljs-keyword">if</span> (<span 
class="hljs-keyword">null</span> == interfaces) {
+        <span class="hljs-keyword">return</span> localAddress;
+    }
+    <span class="hljs-keyword">while</span> (interfaces.hasMoreElements()) {
+        NetworkInterface network = interfaces.nextElement();
+        Enumeration&lt;InetAddress&gt; addresses = network.getInetAddresses();
+        <span class="hljs-keyword">while</span> (addresses.hasMoreElements()) {
+            <span class="hljs-comment">// 返回第一个匹配的适合注册的 IP</span>
+            Optional&lt;InetAddress&gt; addressOp = 
toValidAddress(addresses.nextElement());
+            <span class="hljs-keyword">if</span> (addressOp.isPresent()) {
+                <span class="hljs-keyword">return</span> addressOp.get();
+            }
+        }
+    }
+    <span class="hljs-keyword">return</span> localAddress;
+}
+</code></pre>
+<p>Dubbo 这段选取本地地址的逻辑大致分成了两步</p>
+<ol>
+<li>先去 /etc/hosts 文件中找 hostname 对应的 IP 地址,找到则返回;找不到则转 2</li>
+<li>轮询网卡,寻找合适的 IP 地址,找到则返回;找不到返回 null,在 getLocalAddress0 外侧还有一段逻辑,如果返回 
null,则注册 127.0.0.1 这个本地回环地址</li>
+</ol>
+<p>首先强调下,这段逻辑并没有太大的问题,先别急着挑刺,让我们来分析下其中的一些细节,并进行验证。</p>
+<h3>2.1 尝试获取 hostname 映射 IP</h3>
+<p>Dubbo 首先选取的是 hostname 对应的 IP,在源码中对应的 
<code>InetAddress.getLocalHost();</code>  在 <code>*nix</code> 系统实际部署 Dubbo 
应用时,可以首先使用 <code>hostname</code> 命令获取主机名</p>
+<pre><code class="language-shell">xujingfengdeMacBook-Pro:~ xujingfeng$ 
hostname
+xujingfengdeMacBook-Pro.local
+</code></pre>
+<p>紧接着在 <code>/etc/hosts</code> 配置 IP 映射,为了验证 Dubbo 的机制,我们随意为 hostname 配置一个 IP 
地址</p>
+<pre><code>127.0.0.1   localhost
+1.2.3.4 xujingfengdeMacBook-Pro.local
+</code></pre>
+<p>接着调用 <code>NetUtils.getLocalAddress0()</code> 进行验证,控制台打印如下:</p>
+<pre><code>xujingfengdeMacBook-Pro.local/1.2.3.4
+</code></pre>
+<h3>2.2 判定有效的 IP 地址</h3>
+<p>在 toValidAddress 逻辑中,Dubbo 存在以下逻辑判定一个 IP 地址是否有效</p>
+<pre><code class="language-java"><span class="hljs-function"><span 
class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> 
Optional&lt;InetAddress&gt; <span class="hljs-title">toValidAddress</span><span 
class="hljs-params">(InetAddress address)</span> </span>{
+    <span class="hljs-keyword">if</span> (address <span 
class="hljs-keyword">instanceof</span> Inet6Address) {
+        Inet6Address v6Address = (Inet6Address) address;
+        <span class="hljs-keyword">if</span> (isValidV6Address(v6Address)) {
+            <span class="hljs-keyword">return</span> 
Optional.ofNullable(normalizeV6Address(v6Address));
+        }
+    }
+    <span class="hljs-keyword">if</span> (isValidV4Address(address)) {
+        <span class="hljs-keyword">return</span> Optional.of(address);
+    }
+    <span class="hljs-keyword">return</span> Optional.empty();
+}
+</code></pre>
+<p>依次校验其符合 Ipv6 或者 Ipv4 的 IP 规范,对于 Ipv6 的地址,见如下代码:</p>
+<pre><code class="language-java"><span class="hljs-function"><span 
class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> 
<span class="hljs-title">isValidV6Address</span><span 
class="hljs-params">(Inet6Address address)</span> </span>{
+    <span class="hljs-keyword">boolean</span> preferIpv6 = 
Boolean.getBoolean(<span 
class="hljs-string">"java.net.preferIPv6Addresses"</span>);
+    <span class="hljs-keyword">if</span> (!preferIpv6) {
+        <span class="hljs-keyword">return</span> <span 
class="hljs-keyword">false</span>;
+    }
+    <span class="hljs-keyword">try</span> {
+        <span class="hljs-keyword">return</span> address.isReachable(<span 
class="hljs-number">100</span>);
+    } <span class="hljs-keyword">catch</span> (IOException e) {
+        <span class="hljs-comment">// ignore</span>
+    }
+    <span class="hljs-keyword">return</span> <span 
class="hljs-keyword">false</span>;
+}
+</code></pre>
+<p>首先获取 <code>java.net.preferIPv6Addresses</code> 参数,其默认值为 false,鉴于大多数应用并没有使用 
Ipv6 地址作为理想的注册 IP,这问题不大,紧接着通过 isReachable 判断网卡的连通性。例如一些网卡可能是 
VPN/虚拟网卡的地址,如果没有配置路由表,往往无法连通,可以将之过滤。</p>
+<p>对于 Ipv4 的地址,见如下代码:</p>
+<pre><code class="language-java"><span class="hljs-function"><span 
class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> 
<span class="hljs-title">isValidV4Address</span><span 
class="hljs-params">(InetAddress address)</span> </span>{
+    <span class="hljs-keyword">if</span> (address == <span 
class="hljs-keyword">null</span> || address.isLoopbackAddress()) {
+        <span class="hljs-keyword">return</span> <span 
class="hljs-keyword">false</span>;
+    }
+    String name = address.getHostAddress();
+    <span class="hljs-keyword">boolean</span> result = (name != <span 
class="hljs-keyword">null</span>
+            &amp;&amp; IP_PATTERN.matcher(name).matches()
+            &amp;&amp; !Constants.ANYHOST_VALUE.equals(name)
+            &amp;&amp; !Constants.LOCALHOST_VALUE.equals(name));
+    <span class="hljs-keyword">return</span> result;
+}
+</code></pre>
+<p>对比 Ipv6 的判断,这里我们已经发现前后不对称的情况了</p>
+<ul>
+<li>Ipv4 相比 Ipv6 的逻辑多了 Ipv4 格式的正则校验、本地回环地址校验、ANYHOST 校验</li>
+<li>Ipv4 相比 Ipv6 的逻辑少了网卡连通性的校验</li>
+</ul>
+<p>大家都知道,Ipv4 将 127.0.0.1 定为本地回环地址, Ipv6 也存在回环地址:0:0:0:0:0:0:0:1 或者表示为 
::1。改进建议也很明显,我们放到文末统一总结。</p>
+<h3>2.3 轮询网卡</h3>
+<p>如果上述地址获取为 null 则进入轮询网卡的逻辑(例如 hosts 未指定 hostname 的映射或者 hostname 配置成了 
127.0.0.1 之类的地址便会导致获取到空的网卡地址),轮询网卡对应的源码是 
<code>NetworkInterface.getNetworkInterfaces()</code> 
,这里面涉及的知识点就比较多了,支撑起了我写这篇文章的素材,Dubbo 的逻辑并不复杂,进行简单的校验,返回第一个可用的 IP 即可。</p>
+<p>性子急的读者可能忍不住了,多网卡!合适的网卡可能不止一个,Dubbo 怎么应对呢?按道理说,我们也替 Dubbo 
说句公道话,客官要不你自己指定下?我们首先得对多网卡的场景达成一致看法,才能继续把这篇文章完成下去:我们只能<strong>尽可能</strong>过滤那些“<strong>不对</strong>”的网卡。Dubbo
 看样子对所有网卡是一视同仁了,那么是不是可以尝试优化一下其中的逻辑呢?</p>
+<p>许多开源的服务治理框架在 stackoverflow 或者其 issue 中,注册错 IP 
相关的问题都十分高频,大多数都是轮询网卡出了问题。既然事情发展到这儿,势必需要了解一些网络、网卡的知识,我们才能过滤掉那些明显不适合 RPC 服务注册的 IP 
地址了。</p>
+<h2>3 Ifconfig 介绍</h2>
+<p>我并没有想要让大家对后续的内容望而却步,特地选择了这个大家最熟悉的 Linux 命令!对于那些吐槽:“天呐,都 2019 年了,你怎么还在用 
net-tools/ifconfig,iproute2/ip 了解一下”的言论,请大家视而不见。无论你使用的是 mac,还是 linux,都可以使用它去 
CRUD 你的网卡配置。</p>
+<h3>3.1 常用指令</h3>
+<p><strong>启动关闭指定网卡:</strong></p>
+<pre><code>ifconfig eth0 up
+ifconfig eth0 down
+</code></pre>
+<p><code>ifconfig eth0 up</code> 为启动网卡 eth0,<code>ifconfig eth0 down</code> 
为关闭网卡 eth0。ssh 登陆 linux 服务器操作的用户要小心执行这个操作了,千万不要蠢哭自己。不然你下一步就需要去 google:“禁用 eth0 
网卡后如何远程连接 Linux 服务器” 了。</p>
+<p><strong>为网卡配置和删除IPv6地址:</strong></p>
+<pre><code>ifconfig eth0 add 33ffe:3240:800:1005::2/64    #为网卡eth0配置IPv6地址
+ifconfig eth0 del 33ffe:3240:800:1005::2/64    #为网卡eth0删除IPv6地址
+</code></pre>
+<p><strong>用 ifconfig 修改 MAC 地址:</strong></p>
+<pre><code>ifconfig eth0 hw ether 00:AA:BB:CC:dd:EE
+</code></pre>
+<p><strong>配置 IP 地址:</strong></p>
+<pre><code>[root@localhost ~]# ifconfig eth0 192.168.2.10
+[root@localhost ~]# ifconfig eth0 192.168.2.10 netmask 255.255.255.0
+[root@localhost ~]# ifconfig eth0 192.168.2.10 netmask 255.255.255.0 broadcast 
192.168.2.255
+</code></pre>
+<p><strong>启用和关闭arp协议:</strong></p>
+<pre><code>ifconfig eth0 arp    #开启网卡eth0 的arp协议
+ifconfig eth0 -arp   #关闭网卡eth0 的arp协议
+</code></pre>
+<p><strong>设置最大传输单元:</strong></p>
+<pre><code>ifconfig eth0 mtu 1500    #设置能通过的最大数据包大小为 1500 bytes
+</code></pre>
+<h3>3.2 查看网卡信息</h3>
+<p>在一台 ubuntu 上执行 <code>ifconfig -a</code></p>
+<pre><code class="language-shell">ubuntu@VM-30-130-ubuntu:~$ ifconfig -a
+eth0      Link encap:Ethernet  HWaddr 52:54:00:a9:5f:ae
+          inet addr:10.154.30.130  Bcast:10.154.63.255  Mask:255.255.192.0
+          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
+          RX packets:149673 errors:0 dropped:0 overruns:0 frame:0
+          TX packets:152271 errors:0 dropped:0 overruns:0 carrier:0
+          collisions:0 txqueuelen:1000
+          RX bytes:15205083 (15.2 MB)  TX bytes:21386362 (21.3 MB)
+
+lo        Link encap:Local Loopback
+          inet addr:127.0.0.1  Mask:255.0.0.0
+          UP LOOPBACK RUNNING  MTU:65536  Metric:1
+          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
+          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
+          collisions:0 txqueuelen:1
+          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
+          
+docker0   Link encap:Ethernet  HWaddr 02:42:58:45:c1:15
+          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
+          UP BROADCAST MULTICAST  MTU:1500  Metric:1
+          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
+          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
+          collisions:0 txqueuelen:0
+          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
+
+tun0      Link encap:UNSPEC  HWaddr 
00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+          UP POINTOPOINT NOARP MULTICAST  MTU:1500  Metric:1
+          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
+          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
+          collisions:0 txqueuelen:100
+          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
+</code></pre>
+<p>为了防止黑客对我的 Linux 发起攻击,我还是偷偷对 IP 
做了一点“改造”,请不要为难一个趁着打折+组团购买廉价云服务器的小伙子。对于部分网卡的详细解读:</p>
+<p>eth0 表示第一块网卡, 其中 HWaddr 表示网卡的物理地址,可以看到目前这个网卡的物理地址(MAC 地址)是 
02:42:38:52:70:54</p>
+<p>inet addr 用来表示网卡的 IP 地址,此网卡的 IP 地址是 10.154.30.130,广播地址, Bcast: 
172.18.255.255,掩码地址 Mask:255.255.0.0</p>
+<p>lo 是表示主机的回环地址,这个一般是用来测试一个网络程序,但又不想让局域网或外网的用户能够查看,只能在此台主机上运行和查看所用的网络接口。比如把 
HTTPD 服务器的指定到回坏地址,在浏览器输入 127.0.0.1 就能看到你所架构的 WEB 
网站了。但只有你能看得到,局域网的其它主机或用户则无从知晓。</p>
+<p>第一行:连接类型:Ethernet(以太网)HWaddr(硬件mac地址)</p>
+<p>第二行:网卡的IP地址、子网、掩码</p>
+<p>第三行:UP(代表网卡开启状态)RUNNING(代表网卡的网线被接上)MULTICAST(支持组播)MTU:1500(最大传输单元):1500字节(ifconfig
 不加 -a 则无法看到 DOWN 的网卡)</p>
+<p>第四、五行:接收、发送数据包情况统计</p>
+<p>第七行:接收、发送数据字节数统计信息。</p>
+<p>紧接着的两个网卡 docker0,tun0 是怎么出来的呢?我在我的 ubuntu 上装了 docker 和 
openvpn。这两个东西应该是日常干扰我们做服务注册时的罪魁祸首了,当然,也有可能存在 eth1 这样的第二块网卡。ifconfig -a 
看到的东西就对应了 JDK 的 api :<code>NetworkInterface.getNetworkInterfaces()</code> 
。我们简单做个总结,大致有三个干扰因素</p>
+<ul>
+<li>以 docker 网桥为首的虚拟网卡地址,毕竟这东西这么火,怎么也得单独列出来吧?</li>
+<li>以 TUN/TAP 为代表的虚拟网卡地址,多为 VPN 场景</li>
+<li>以 eth1 为代表的多网卡场景,有钱就可以装多网卡了!</li>
+</ul>
+<p>我们后续的篇幅将针对这些场景做分别的介绍,力求让大家没吃过猪肉,起码看下猪怎么跑的。</p>
+<h2>4 干扰因素一:Docker 网桥</h2>
+<p>熟悉 docker 的朋友应该知道 docker 会默认创建一个 docker0 的网桥,供容器实例连接。如果嫌默认的网桥不够直观,我们可以使用 
bridge 模式自定义创建一个新的网桥:</p>
+<pre><code class="language-shell">ubuntu@VM-30-130-ubuntu:~$ docker network 
create kirito-bridge
+a38696dbbe58aa916894c674052c4aa6ab32266dcf6d8111fb794b8a344aa0d9
+ubuntu@VM-30-130-ubuntu:~$ ifconfig -a
+br-a38696dbbe58 Link encap:Ethernet  HWaddr 02:42:6e:aa:fd:0c
+          inet addr:172.19.0.1  Bcast:172.19.255.255  Mask:255.255.0.0
+          UP BROADCAST MULTICAST  MTU:1500  Metric:1
+          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
+          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
+          collisions:0 txqueuelen:0
+          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
+</code></pre>
+<p>使用 docker network 指令创建网桥之后,自动创建了对应的网卡,我只给出了 <code>ifconfig -a</code> 
的增量返回部分,可以看出多了一个 br-a38696dbbe58 的网卡。</p>
+<p>我有意区分了“网桥”和“网卡”,可以使用 bridge-utils/brctl 来查看网桥信息:</p>
+<pre><code class="language-shell">ubuntu@VM-30-130-ubuntu:~$ sudo brctl show
+bridge name    bridge id               STP enabled     interfaces
+br-a38696dbbe58                8000.02426eaafd0c       no
+docker0                8000.02425845c215       no
+</code></pre>
+<p>网桥是一个虚拟设备,这个设备只有 brctl show 能看到,网桥创建之后,会自动创建一个同名的网卡,并将这个网卡加入网桥。</p>
+<h2>5 干扰因素二:TUN/TAP 虚拟网络设备</h2>
+<p>平时我们所说的虚拟网卡、虚拟机,大致都跟 TUN/TAP 有关。我的读者大多数是 Java 
从业者,相信我下面的内容并没有太超纲,不要被陌生的名词唬住。对于被唬住的读者,也可以直接跳过 5.1~5.3,直接看 5.4 的实战。</p>
+<h3>5.1 真实网卡工作原理</h3>
+<p><img src="http://kirito.iocoder.cn/1918847-496d0e96c237f25a.png"; 
alt="1918847-496d0e96c237f25a"></p>
+<p>上图中的 <strong>eth0</strong> 表示我们主机已有的真实的网卡接口 
(<strong>interface</strong>)。</p>
+<p>网卡接口 <strong>eth0</strong> 
所代表的真实网卡通过网线(<strong>wire</strong>)和外部网络相连,该物理网卡收到的数据包会经由接口 
<strong>eth0</strong> 传递给内核的网络协议栈(<strong>Network 
Stack</strong>)。然后协议栈对这些数据包进行进一步的处理。</p>
+<p>对于一些错误的数据包,协议栈可以选择丢弃;对于不属于本机的数据包,协议栈可以选择转发;而对于确实是传递给本机的数据包,而且该数据包确实被上层的应用所需要,协议栈会通过
 <strong>Socket API</strong> 告知上层正在等待的应用程序。</p>
+<h3>5.2 TUN 工作原理</h3>
+<p><img src="http://kirito.iocoder.cn/1918847-85ea08bc89d9427e.png"; 
alt="1918847-85ea08bc89d9427e"></p>
+<p>我们知道,普通的网卡是通过网线来收发数据包的话,而 <strong>TUN</strong> 设备比较特殊,它通过一个文件收发数据包。</p>
+<p>如上图所示,<strong>tunX</strong> 和上面的 <strong>eth0</strong> 在逻辑上面是等价的, 
<strong>tunX</strong> 也代表了一个网络接口,虽然这个接口是系统通过软件所模拟出来的.</p>
+<p>网卡接口 <strong>tunX 所代表的虚拟网卡通过文件 /dev/tunX 与我们的应用程序(App)相连</strong>,应用程序每次使用 
<strong>write</strong> 之类的系统调用将数据写入该文件,这些数据会以网络层数据包的形式,通过该虚拟网卡,经由网络接口 
<strong>tunX</strong> 传递给网络协议栈,同时该应用程序也可以通过 <strong>read</strong> 之类的系统调用,经由文件 
<strong>/dev/tunX</strong> 读取到协议栈向 <strong>tunX</strong> 
传递的<strong>所有</strong>数据包。</p>
+<p>此外,协议栈可以像操纵普通网卡一样来操纵 <strong>tunX</strong> 所代表的虚拟网卡。比如说,给 
<strong>tunX</strong> 设定 <strong>IP</strong> 
地址,设置路由,总之,在协议栈看来,<strong>tunX</strong> 所代表的网卡和其他普通的网卡区别不大,当然,硬要说区别,那还是有的,那就是 
<strong>tunX</strong> 设备不存在 <strong>MAC</strong> 
地址,这个很好理解,<strong>tunX</strong> 只模拟到了网络层,要 <strong>MAC</strong>地址没有任何意义。当然,如果是 
<strong>tapX</strong> 的话,在协议栈的眼中,<strong>tapX</strong> 和真实网卡没有任何区别。</p>
+<p>是不是有些懵了?我是谁,为什么我要在这篇文章里面学习 TUN!因为我们常用的 VPN 基本就是基于 TUN/TAP 搭建的,如果我们使用 
<strong>TUN</strong> 设备搭建一个基于 <strong>UDP</strong> 的 <strong>VPN</strong> 
,那么整个处理过程可能是这幅样子:</p>
+<p><img src="http://kirito.iocoder.cn/1918847-ac4155ec7e9489b2.png"; 
alt="1918847-ac4155ec7e9489b2"></p>
+<h3>5.3 TAP 工作原理</h3>
+<p><strong>TAP</strong> 设备与 <strong>TUN</strong> 设备工作方式完全相同,区别在于:</p>
+<ol>
+<li><strong>TUN</strong> 设备是一个三层设备,它只模拟到了 <strong>IP</strong> 层,即网络层 我们可以通过 
<strong>/dev/tunX</strong> 文件收发 <strong>IP</strong> 层数据包,它无法与物理网卡做 
<strong>bridge</strong>,但是可以通过三层交换(如  
<strong>ip_forward</strong>)与物理网卡连通。可以使用<code>ifconfig</code>之类的命令给该设备设定 
<strong>IP</strong> 地址。</li>
+<li><strong>TAP</strong> 设备是一个二层设备,它比 <strong>TUN</strong> 更加深入,通过 
<strong>/dev/tapX</strong> 文件可以收发 <strong>MAC</strong> 层数据包,即数据链路层,拥有 
<strong>MAC</strong> 层功能,可以与物理网卡做 <strong>bridge</strong>,支持 
<strong>MAC</strong> 层广播。同样的,我们也可以通过<code>ifconfig</code>之类的命令给该设备设定 
<strong>IP</strong> 地址,你如果愿意,我们可以给它设定 <strong>MAC</strong> 地址。</li>
+</ol>
+<p>关于文章中出现的二层,三层,我这里说明一下,第一层是物理层,第二层是数据链路层,第三层是网络层,第四层是传输层。</p>
+<h3>5.4 openvpn 实战</h3>
+<p>openvpn 是 Linux 上一款开源的 vpn 工具,我们通过它来复现出影响我们做网卡选择的场景。</p>
+<p>安装 openvpn</p>
+<pre><code class="language-shell">sudo apt-get install openvpn
+</code></pre>
+<p>安装一个 TUN 设备:</p>
+<pre><code class="language-shell">ubuntu@VM-30-130-ubuntu:~$ sudo openvpn 
--mktun --dev tun0
+Mon Apr 29 22:23:31 2019 TUN/TAP device tun0 opened
+Mon Apr 29 22:23:31 2019 Persist state set to: ON
+</code></pre>
+<p>安装一个 TAP 设备:</p>
+<pre><code class="language-shell">ubuntu@VM-30-130-ubuntu:~$ sudo openvpn 
--mktun --dev tap0
+Mon Apr 29 22:24:36 2019 TUN/TAP device tap0 opened
+Mon Apr 29 22:24:36 2019 Persist state set to: ON
+</code></pre>
+<p>执行 <code>ifconfig -a</code> 查看网卡,只给出增量的部分:</p>
+<pre><code class="language-shell">tap0      Link encap:Ethernet  HWaddr 
7a:a2:a8:f1:6b:df
+          BROADCAST MULTICAST  MTU:1500  Metric:1
+          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
+          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
+          collisions:0 txqueuelen:100
+          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
+
+tun0      Link encap:UNSPEC  HWaddr 
00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+          inet addr:10.154.30.131  P-t-P:10.154.30.131  Mask:255.255.255.255
+          UP POINTOPOINT NOARP MULTICAST  MTU:1500  Metric:1
+          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
+          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
+          collisions:0 txqueuelen:100
+          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
+</code></pre>
+<p>这样就解释了文章一开始为什么会有 tun0 这样的网卡了。这里读者可能会有疑惑,使用 ifconfig 不是也可以创建 tap 和 tun 
网卡吗?当然啦,openvpn 是一个 vpn 工具,只能创建名为 tunX/tapX 的网卡,其遵守着一定的规范,ifconfig 
可以随意创建,但没人认那些随意创建的网卡。</p>
+<h2>6 干扰因素三:多网卡</h2>
+<p><img src="http://kirito.iocoder.cn/image-20190429223515625.png"; 
alt="image-20190429223515625"></p>
+<p>这个没有太多好说的,有多张真实的网卡,从普哥那儿搞到如上的 IP 信息。</p>
+<h2>7 MAC 下的差异</h2>
+<p>虽然 ifconfig 等指令是 <code>*nux</code> 通用的,但是其展示信息,网卡相关的属性和命名都有较大的差异。例如这是我 MAC 
下执行 <code>ifconfig -a</code> 的返回:</p>
+<pre><code class="language-shell">xujingfengdeMacBook-Pro:dubbo-in-action 
xujingfeng$ ifconfig -a
+lo0: flags=8049&lt;UP,LOOPBACK,RUNNING,MULTICAST&gt; mtu 16384
+       options=1203&lt;RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP&gt;
+       inet 127.0.0.1 netmask 0xff000000
+       inet6 ::1 prefixlen 128
+       inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
+       nd6 options=201&lt;PERFORMNUD,DAD&gt;
+gif0: flags=8010&lt;POINTOPOINT,MULTICAST&gt; mtu 1280
+stf0: flags=0&lt;&gt; mtu 1280
+XHC0: flags=0&lt;&gt; mtu 0
+XHC20: flags=0&lt;&gt; mtu 0
+en0: flags=8863&lt;UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST&gt; mtu 1500
+       ether 88:e9:fe:88:a0:76
+       inet6 fe80::1cab:f689:60d1:bacb%en0 prefixlen 64 secured scopeid 0x6
+       inet 30.130.11.242 netmask 0xffffff80 broadcast 30.130.11.255
+       nd6 options=201&lt;PERFORMNUD,DAD&gt;
+       media: autoselect
+       status: active
+p2p0: flags=8843&lt;UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST&gt; mtu 2304
+       ether 0a:e9:fe:88:a0:76
+       media: autoselect
+       status: inactive
+awdl0: flags=8943&lt;UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST&gt; mtu 
1484
+       ether 66:d2:8c:8c:dd:85
+       inet6 fe80::64d2:8cff:fe8c:dd85%awdl0 prefixlen 64 scopeid 0x8
+       nd6 options=201&lt;PERFORMNUD,DAD&gt;
+       media: autoselect
+       status: active
+en1: flags=8963&lt;UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST&gt; 
mtu 1500
+       options=60&lt;TSO4,TSO6&gt;
+       ether aa:00:d0:13:0e:01
+       media: autoselect &lt;full-duplex&gt;
+       status: inactive
+en2: flags=8963&lt;UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST&gt; 
mtu 1500
+       options=60&lt;TSO4,TSO6&gt;
+       ether aa:00:d0:13:0e:00
+       media: autoselect &lt;full-duplex&gt;
+       status: inactive
+bridge0: flags=8863&lt;UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST&gt; mtu 
1500
+       options=63&lt;RXCSUM,TXCSUM,TSO4,TSO6&gt;
+       ether aa:00:d0:13:0e:01
+       Configuration:
+               id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
+               maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
+               root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
+               ipfilter disabled flags 0x2
+       member: en1 flags=3&lt;LEARNING,DISCOVER&gt;
+               ifmaxaddr 0 port 9 priority 0 path cost 0
+       member: en2 flags=3&lt;LEARNING,DISCOVER&gt;
+               ifmaxaddr 0 port 10 priority 0 path cost 0
+       nd6 options=201&lt;PERFORMNUD,DAD&gt;
+       media: &lt;unknown type&gt;
+       status: inactive
+utun0: flags=8051&lt;UP,POINTOPOINT,RUNNING,MULTICAST&gt; mtu 2000
+       inet6 fe80::3fe0:3e8b:384:9968%utun0 prefixlen 64 scopeid 0xc
+       nd6 options=201&lt;PERFORMNUD,DAD&gt;
+utun1: flags=8051&lt;UP,POINTOPOINT,RUNNING,MULTICAST&gt; mtu 1380
+       inet6 fe80::7894:3abc:5abd:457d%utun1 prefixlen 64 scopeid 0xd
+       nd6 options=201&lt;PERFORMNUD,DAD&gt;  
+</code></pre>
+<p>内容很多,我挑几点差异简述下:</p>
+<ul>
+<li>
+<p>内容展示形式不一样,没有 Linux 下的接收、发送数据字节数等统计信息</p>
+</li>
+<li>
+<p>真实网卡的命名不一样:eth0 -&gt; en0</p>
+</li>
+<li>
+<p>虚拟网卡的命名格式不一样:tun/tap -&gt; utun</p>
+</li>
+</ul>
+<p>对于这些常见网卡命名的解读,我摘抄一部分来自 stackoverflow 的回答:</p>
+<blockquote>
+<p>In arbitrary order of my familarity / widespread relevance:</p>
+<p><code>lo0</code> is loopback.</p>
+<p><code>en0</code> at one point &quot;ethernet&quot;, now is WiFi (and I have 
no idea what extra <code>en1</code> or <code>en2</code> are used for).</p>
+<p><code>fw0</code> is the FireWire network interface.</p>
+<p><code>stf0</code> is an <a 
href="https://www.freebsd.org/cgi/man.cgi?gif(4)">IPv6 to IPv4 tunnel 
interface</a> to support <a href="http://en.wikipedia.org/wiki/6to4";>the 
transition</a> from IPv4 to the IPv6 standard.</p>
+<p><code>gif0</code> is a more <a 
href="https://www.freebsd.org/cgi/man.cgi?gif(4)">generic tunneling 
interface</a> [46]-to-[46].</p>
+<p><code>awdl0</code> is <a 
href="https://stackoverflow.com/questions/19587701/what-is-awdl-apple-wireless-direct-link-and-how-does-it-work";>Apple
 Wireless Direct Link</a></p>
+<p><code>p2p0</code> is related to AWDL features. Either as an old version, or 
virtual interface with different semantics than <code>awdl</code>.</p>
+<p>the &quot;Network&quot; panel in System Preferences to see what network 
devices &quot;exist&quot; or &quot;can exist&quot; with current 
configuration.</p>
+<p>many VPNs will add additional devices, often &quot;utun#&quot; or 
&quot;utap#&quot; following <a 
href="https://en.wikipedia.org/wiki/TUN/TAP";>TUN/TAP (L3/L2)</a>virtual 
networking devices.</p>
+<p>use <code>netstat -nr</code> to see how traffic is currently routed via 
network devices according to destination.</p>
+<p>interface naming conventions started in BSD were retained in OS X / macOS, 
and now there also additions.</p>
+</blockquote>
+<h2>8 Dubbo 改进建议</h2>
+<p>我们进行了以上探索,算是对网卡有一点了解了。回过头来看看 Dubbo 获取网卡的逻辑,是否可以做出改进呢?</p>
+<p><strong>Dubbo Action 1:</strong></p>
+<p>保持 Ipv4 和 Ipv6 的一致性校验。为 Ipv4 增加连通性校验;为 Ipv6 增加 LoopBack 和 ANYHOST 等校验。</p>
+<p><strong>Dubbo Action 2:</strong></p>
+<pre><code class="language-java">NetworkInterface network = 
interfaces.nextElement();
+<span class="hljs-keyword">if</span> (network.isLoopback() || 
network.isVirtual() || !network.isUp()) {
+    <span class="hljs-keyword">continue</span>;
+}
+</code></pre>
+<p>JDK 提供了以上的 API,我们可以利用起来,过滤一部分一定不正确的网卡。</p>
+<p><strong>Dubbo Action 3:</strong></p>
+<p>我们本文花了较多的篇幅介绍了 docker 和 TUN/TAP 两种场景导致的虚拟网卡的问题,算是较为常见的一个影响因素,虽然他们的命名具有固定性,如 
docker0、tunX、tapX,但我觉得通过网卡名称的判断方式去过滤注册 IP 有一些 hack,所以不建议 dubbo contributor 
提出相应的 pr 去增加这些 hack 判断,尽管可能会对判断有所帮助。</p>
+<p>对于真实多网卡、内外网 IP 
共存的场景,不能仅仅是框架侧在做努力,用户也需要做一些事,就像爱情一样,我可以主动一点,但你也得反馈,才能发展出故事。</p>
+<p><strong>Dubbo User Action 1:</strong></p>
+<p>可以配置 <code>/etc/hosts</code> 文件,将 hostname 对应的 IP 显式配置进去。</p>
+<p><strong>Dubbo User Action 2:</strong></p>
+<p>可以使用启动参数去显式指定注册的 IP:</p>
+<pre><code class="language-java">-DDUBBO_IP_TO_REGISTRY=<span 
class="hljs-number">1.2</span>.3.4
+</code></pre>
+<p>也可以指定 Dubbo 服务绑定在哪块网卡上:</p>
+<pre><code class="language-java">-DDUBBO_IP_TO_BIND=<span 
class="hljs-number">1.2</span>.3.4
+</code></pre>
+<h2>9 参考文章</h2>
+<p><a href="https://www.jianshu.com/p/09f9375b7fa7";>TUN/TAP 设备浅析</a></p>
+<p><a 
href="https://stackoverflow.com/questions/29958143/what-are-en0-en1-p2p-and-so-on-that-are-displayed-after-executing-ifconfig";>what-are-en0-en1-p2p-and-so-on-that-are-displayed-after-executing-ifconfig</a></p>
+</section><footer class="footer-container"><div class="footer-body"><img 
src="/img/dubbo_gray.png"/><img class="apache" src="/img/apache_logo.png"/><div 
class="cols-container"><div class="col col-12"><h3></h3><p></p></div><div 
class="col col-4"><dl><dt>ASF</dt><dd><a href="http://www.apache.org"; 
target="_self">基金会</a></dd><dd><a href="http://www.apache.org/licenses/"; 
target="_self">证书</a></dd><dd><a 
href="http://www.apache.org/events/current-event"; 
target="_self">事件</a></dd><dd><a href=" [...]
+       <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-network-interfaces.json 
b/zh-cn/blog/dubbo-network-interfaces.json
new file mode 100644
index 0000000..92380d9
--- /dev/null
+++ b/zh-cn/blog/dubbo-network-interfaces.json
@@ -0,0 +1,10 @@
+{
+  "filename": "dubbo-network-interfaces.md",
+  "__html": "<h1>研究 Dubbo 网卡地址注册时的一点思考</h1>\n<h2>1 
如何选择合适的网卡地址</h2>\n<p>可能相当一部分人还不知道我这篇文章到底要讲什么,我说个场景,大家应该就明晰了。在分布式服务调用过程中,以 Dubbo 
为例,服务提供者往往需要将自身的 IP 地址上报给注册中心,供消费者去发现。在大多数情况下 Dubbo 都可以正常工作,但如果你留意过 Dubbo 的 
github issue,其实有不少人反馈:Dubbo Provider 注册了错误的 
IP。如果你能立刻联想到:多网卡、内外网地址共存、VPN、虚拟网卡等关键词,那我建议你一定要继续将本文看下去,因为我也想到了这些,它们都是本文所要探讨的东西!那么“如何选择合适的网卡地址”呢,Dubbo
 现有的逻辑到底算不算完备?我们不急着回答它,而是带着这些问题一起进行研究,相信到文末,其中答案,各位看官自有
 评说。</p>\n<h2>2 Dubbo 是怎么做的</h2>\n<p>Dubbo 
获取网卡地址的逻辑在各个版本中也是千回百转,走过弯路,也做过优化,我们用最新的 2.7 [...]
+  "link": "/zh-cn/blog/dubbo-network-interfaces.html",
+  "meta": {
+    "title": "研究 Dubbo 网卡地址注册时的一点思考",
+    "keywords": "网卡地址注册",
+    "description": "研究 Dubbo 网卡地址注册时的一点思考"
+  }
+}
\ No newline at end of file
diff --git a/zh-cn/blog/dubbo-registry-nacos-integration.html 
b/zh-cn/blog/dubbo-registry-nacos-integration.html
index 201a851..04e4d3e 100644
--- a/zh-cn/blog/dubbo-registry-nacos-integration.html
+++ b/zh-cn/blog/dubbo-registry-nacos-integration.html
@@ -13,9 +13,9 @@
 </head>
 <body>
        <div id="root"><div class="blog-detail-page" data-reactroot=""><header 
class="header-container header-container-normal"><div class="header-body"><a 
href="/zh-cn/index.html"><img class="logo" 
src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span 
class="icon-search"></span></div><span class="language-switch 
language-switch-normal">En</span><div class="header-menu"><img 
class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item 
menu-item-normal"><a h [...]
-<p>Nacos 作为 Dubbo 生态系统中重要的注册中心实现,其中 <a 
href="https://github.com/dubbo/dubbo-registry-nacos";><code>dubbo-registry-nacos</code></a>
 则是 Dubbo 融合 Nacos 注册中心的实现。</p>
+<p>Nacos 作为 Dubbo 生态系统中重要的注册中心实现,其中 <a 
href="https://github.com/apache/incubator-dubbo/tree/master/dubbo-registry/dubbo-registry-nacos";><code>dubbo-registry-nacos</code></a>
 则是 Dubbo 融合 Nacos 注册中心的实现。</p>
 <h2>预备工作</h2>
-<p>当您将 <a 
href="https://github.com/dubbo/dubbo-registry-nacos";><code>dubbo-registry-nacos</code></a>
 整合到您的 Dubbo 工程之前,请确保后台已经启动 Nacos 服务。如果您尚且不熟悉 Nacos 的基本使用的话,可先行参考 <a 
href="https://nacos.io/en-us/docs/quick-start.html";>Nacos 快速入门</a>:<a 
href="https://nacos.io/en-us/docs/quick-start.html%E3%80%82%E5%BB%BA%E8%AE%AE%E4%BD%BF%E7%94%A8";>https://nacos.io/en-us/docs/quick-start.html。建议使用</a>
 Nacos <code>0.6.1</code> 以上的版本。</p>
+<p>当您将 <a 
href="https://github.com/apache/incubator-dubbo/tree/master/dubbo-registry/dubbo-registry-nacos";><code>dubbo-registry-nacos</code></a>
 整合到您的 Dubbo 工程之前,请确保后台已经启动 Nacos 服务。如果您尚且不熟悉 Nacos 的基本使用的话,可先行参考 <a 
href="https://nacos.io/en-us/docs/quick-start.html";>Nacos 快速入门</a>:<a 
href="https://nacos.io/en-us/docs/quick-start.html%E3%80%82%E5%BB%BA%E8%AE%AE%E4%BD%BF%E7%94%A8";>https://nacos.io/en-us/docs/quick-start.html。建议使用</a>
 Nacos <code>0.6.1</code> 以上的版本。</p>
 <h2>快速上手</h2>
 <p>Dubbo 融合 Nacos 成为注册中心的操作步骤非常简单,大致步骤可分为“增加 Maven 依赖”以及“配置注册中心“。</p>
 <h3>增加 Maven 依赖</h3>
@@ -408,11 +408,11 @@ Service [name :null , port : 20883] 
sayName(&quot;小马哥(mercyblitz)&quot
 Service [name :null , port : 20883] sayName(&quot;小马哥(mercyblitz)&quot;) : 
Hello,小马哥(mercyblitz)
 Service [name :null , port : 20883] sayName(&quot;小马哥(mercyblitz)&quot;) : 
Hello,小马哥(mercyblitz)
 </code></pre>
-<p>结果同样运行和负载均衡正常,不过由于当前示例尚未添加属性 <code>demo.service.name</code> 
的缘故,因此,“name”部分信息输出为 <code>null</code>。更多内容请参考:<a 
href="https://github.com/dubbo/dubbo-registry-nacos%E3%80%82";>https://github.com/dubbo/dubbo-registry-nacos。</a></p>
+<p>结果同样运行和负载均衡正常,不过由于当前示例尚未添加属性 <code>demo.service.name</code> 
的缘故,因此,“name”部分信息输出为 <code>null</code>。更多内容请参考:<a 
href="https://github.com/apache/incubator-dubbo/tree/master/dubbo-registry/dubbo-registry-nacos%E3%80%82";>https://github.com/apache/incubator-dubbo/tree/master/dubbo-registry/dubbo-registry-nacos。</a></p>
 <p>如果您关注或喜爱 Dubbo 以及 Nacos 等开源工程,不妨为它们点 “star”,加油打气链接:</p>
 <ul>
 <li>Apache Dubbo:<a 
href="https://github.com/apache/incubator-dubbo";>https://github.com/apache/incubator-dubbo</a></li>
-<li>Dubbo Nacos Registry:<a 
href="https://github.com/dubbo/dubbo-registry-nacos";>https://github.com/dubbo/dubbo-registry-nacos</a></li>
+<li>Dubbo Nacos Registry:<a 
href="https://github.com/apache/incubator-dubbo/tree/master/dubbo-registry/dubbo-registry-nacos";>https://github.com/apache/incubator-dubbo/tree/master/dubbo-registry/dubbo-registry-nacos</a></li>
 <li>Alibaba Nacos:<a 
href="https://github.com/alibaba/nacos";>https://github.com/alibaba/nacos</a></li>
 </ul>
 </section><footer class="footer-container"><div class="footer-body"><img 
src="/img/dubbo_gray.png"/><img class="apache" src="/img/apache_logo.png"/><div 
class="cols-container"><div class="col col-12"><h3></h3><p></p></div><div 
class="col col-4"><dl><dt>ASF</dt><dd><a href="http://www.apache.org"; 
target="_self">基金会</a></dd><dd><a href="http://www.apache.org/licenses/"; 
target="_self">证书</a></dd><dd><a 
href="http://www.apache.org/events/current-event"; 
target="_self">事件</a></dd><dd><a href=" [...]
diff --git a/zh-cn/blog/dubbo-registry-nacos-integration.json 
b/zh-cn/blog/dubbo-registry-nacos-integration.json
index 82c7661..fe8b3a2 100644
--- a/zh-cn/blog/dubbo-registry-nacos-integration.json
+++ b/zh-cn/blog/dubbo-registry-nacos-integration.json
@@ -1,6 +1,6 @@
 {
   "filename": "dubbo-registry-nacos-integration.md",
-  "__html": "<h1>Dubbo 融合 Nacos 成为注册中心</h1>\n<p>Nacos 作为 Dubbo 
生态系统中重要的注册中心实现,其中 <a 
href=\"https://github.com/dubbo/dubbo-registry-nacos\";><code>dubbo-registry-nacos</code></a>
 则是 Dubbo 融合 Nacos 注册中心的实现。</p>\n<h2>预备工作</h2>\n<p>当您将 <a 
href=\"https://github.com/dubbo/dubbo-registry-nacos\";><code>dubbo-registry-nacos</code></a>
 整合到您的 Dubbo 工程之前,请确保后台已经启动 Nacos 服务。如果您尚且不熟悉 Nacos 的基本使用的话,可先行参考 <a 
href=\"https://nacos.io/en-us/docs/quick-start.html\";>Nacos 快速入门</a>:<a 
href=\"https://nacos.io/e [...]
+  "__html": "<h1>Dubbo 融合 Nacos 成为注册中心</h1>\n<p>Nacos 作为 Dubbo 
生态系统中重要的注册中心实现,其中 <a 
href=\"https://github.com/apache/incubator-dubbo/tree/master/dubbo-registry/dubbo-registry-nacos\";><code>dubbo-registry-nacos</code></a>
 则是 Dubbo 融合 Nacos 注册中心的实现。</p>\n<h2>预备工作</h2>\n<p>当您将 <a 
href=\"https://github.com/apache/incubator-dubbo/tree/master/dubbo-registry/dubbo-registry-nacos\";><code>dubbo-registry-nacos</code></a>
 整合到您的 Dubbo 工程之前,请确保后台已经启动 Nacos 服务。如果您尚且不熟悉 Nacos 的基本使用的话,可先行参考 <a href=\"ht 
[...]
   "link": "/zh-cn/blog/dubbo-registry-nacos-integration.html",
   "meta": {}
 }
\ No newline at end of file
diff --git a/zh-cn/blog/gsoc-2018.html b/zh-cn/blog/gsoc-2018.html
new file mode 100644
index 0000000..cec630c
--- /dev/null
+++ b/zh-cn/blog/gsoc-2018.html
@@ -0,0 +1,34 @@
+<!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, GSoC" />
+       <meta name="description" content="谷歌编程之夏会议上2018个项目被宣布,Dubbo位列其中。" />
+       <!-- 网页标签标题 -->
+       <title>谷歌编程之夏会议上2018个项目被宣布</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=""><header 
class="header-container header-container-normal"><div class="header-body"><a 
href="/zh-cn/index.html"><img class="logo" 
src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span 
class="icon-search"></span></div><span class="language-switch 
language-switch-normal">En</span><div class="header-menu"><img 
class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item 
menu-item-normal"><a h [...]
+<p>谷歌编程之夏会议上2018个项目被宣布, Raghu Reddy 的项目&quot;Apache Dubbo 扩展串行协议支持&quot; 被<a 
href="https://summerofcode.withgoogle.com/projects/#4747840161579008";>接受</a>! 
祝贺他!</p>
+</section><footer class="footer-container"><div class="footer-body"><img 
src="/img/dubbo_gray.png"/><img class="apache" src="/img/apache_logo.png"/><div 
class="cols-container"><div class="col col-12"><h3></h3><p></p></div><div 
class="col col-4"><dl><dt>ASF</dt><dd><a href="http://www.apache.org"; 
target="_self">基金会</a></dd><dd><a href="http://www.apache.org/licenses/"; 
target="_self">证书</a></dd><dd><a 
href="http://www.apache.org/events/current-event"; 
target="_self">事件</a></dd><dd><a href=" [...]
+       <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/gsoc-2018.json b/zh-cn/blog/gsoc-2018.json
new file mode 100644
index 0000000..ec34a25
--- /dev/null
+++ b/zh-cn/blog/gsoc-2018.json
@@ -0,0 +1,10 @@
+{
+  "filename": "gsoc-2018.md",
+  "__html": "<h2>谷歌编程之夏会议上2018个项目被宣布</h2>\n<p>谷歌编程之夏会议上2018个项目被宣布, Raghu Reddy 
的项目&quot;Apache Dubbo 扩展串行协议支持&quot; 被<a 
href=\"https://summerofcode.withgoogle.com/projects/#4747840161579008\";>接受</a>! 
祝贺他!</p>\n",
+  "link": "/zh-cn/blog/gsoc-2018.html",
+  "meta": {
+    "title": "谷歌编程之夏会议上2018个项目被宣布",
+    "keywords": "Dubbo, GSoC",
+    "description": "谷歌编程之夏会议上2018个项目被宣布,Dubbo位列其中。"
+  }
+}
\ No newline at end of file
diff --git a/zh-cn/blog/index.html b/zh-cn/blog/index.html
index 6382723..523c784 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=""><header 
class="header-container header-container-normal"><div class="header-body"><a 
href="/zh-cn/index.html"><img class="logo" 
src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span 
class="icon-search"></span></div><span class="language-switch 
language-switch-normal">En</span><div class="header-menu"><img 
class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item 
menu-item-normal"><a hre [...]
+       <div id="root"><div class="blog-list-page" data-reactroot=""><header 
class="header-container header-container-normal"><div class="header-body"><a 
href="/zh-cn/index.html"><img class="logo" 
src="/img/dubbo_colorful.png"/></a><div class="search search-normal"><span 
class="icon-search"></span></div><span class="language-switch 
language-switch-normal">En</span><div class="header-menu"><img 
class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item 
menu-item-normal"><a hre [...]
        <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/prepare-an-apache-release.html 
b/zh-cn/blog/prepare-an-apache-release.html
index c8d25a3..4e9705b 100644
--- a/zh-cn/blog/prepare-an-apache-release.html
+++ b/zh-cn/blog/prepare-an-apache-release.html
@@ -5,7 +5,7 @@
        <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, Apache, Release" />
-       <meta name="description" content="prepare-an-apache-release" />
+       <meta name="description" content="本文介绍了Apache如何发布内容和流程" />
        <!-- 网页标签标题 -->
        <title>如何准备Apache Release</title>
        <link rel="shortcut icon" href="/img/dubbo.ico"/>
diff --git a/zh-cn/blog/prepare-an-apache-release.json 
b/zh-cn/blog/prepare-an-apache-release.json
index fafb88d..8eb68b0 100644
--- a/zh-cn/blog/prepare-an-apache-release.json
+++ b/zh-cn/blog/prepare-an-apache-release.json
@@ -4,6 +4,7 @@
   "link": "/zh-cn/blog/prepare-an-apache-release.html",
   "meta": {
     "title": "如何准备Apache Release",
-    "keywords": "Dubbo, Apache, Release"
+    "keywords": "Dubbo, Apache, Release",
+    "description": "本文介绍了Apache如何发布内容和流程"
   }
 }
\ No newline at end of file
diff --git a/zh-cn/docs/user/references/registry/zookeeper.html 
b/zh-cn/docs/user/references/registry/zookeeper.html
index 56cd136..fa7f2cc 100644
--- a/zh-cn/docs/user/references/registry/zookeeper.html
+++ b/zh-cn/docs/user/references/registry/zookeeper.html
@@ -41,6 +41,7 @@
 </code></pre>
 <p>或直接<a 
href="http://repo1.maven.org/maven2/org/apache/zookeeper/zookeeper";>下载</a>。</p>
 <p>Dubbo 支持 zkclient 和 curator 两种 Zookeeper 客户端实现:</p>
+<p><strong>注意:在2.7.x的版本中已经移除了zkclient的实现,如果要使用zkclient客户端,需要自行拓展</strong></p>
 <h3>使用 zkclient 客户端</h3>
 <p>从 <code>2.2.0</code> 版本开始缺省为 zkclient 实现,以提升 zookeeper 客户端的健状性。<a 
href="https://github.com/sgroschupf/zkclient";>zkclient</a> 是 Datameer 开源的一个 
Zookeeper 客户端实现。</p>
 <p>缺省配置:</p>
diff --git a/zh-cn/docs/user/references/registry/zookeeper.json 
b/zh-cn/docs/user/references/registry/zookeeper.json
index ca538d9..8930582 100644
--- a/zh-cn/docs/user/references/registry/zookeeper.json
+++ b/zh-cn/docs/user/references/registry/zookeeper.json
@@ -1,6 +1,6 @@
 {
   "filename": "zookeeper.md",
-  "__html": "<h1>zookeeper 注册中心</h1>\n<p><a 
href=\"http://zookeeper.apache.org\";>Zookeeper</a> 是 Apacahe Hadoop 
的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,并推荐使用 <sup 
class=\"footnote-ref\"><a href=\"#fn1\" 
id=\"fnref1\">[1]</a></sup>。</p>\n<p><img 
src=\"../../sources/images/zookeeper.jpg\" 
alt=\"/user-guide/images/zookeeper.jpg\"></p>\n<p>流程说明:</p>\n<ul>\n<li>服务提供者启动时:
 向 <code>/dubbo/com.foo.BarService/providers</code> 目录下写入自己的 URL 
地址</li>\n<li>服务消费者启动时: 订阅 <code>/dubbo/com [...]
+  "__html": "<h1>zookeeper 注册中心</h1>\n<p><a 
href=\"http://zookeeper.apache.org\";>Zookeeper</a> 是 Apacahe Hadoop 
的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,并推荐使用 <sup 
class=\"footnote-ref\"><a href=\"#fn1\" 
id=\"fnref1\">[1]</a></sup>。</p>\n<p><img 
src=\"../../sources/images/zookeeper.jpg\" 
alt=\"/user-guide/images/zookeeper.jpg\"></p>\n<p>流程说明:</p>\n<ul>\n<li>服务提供者启动时:
 向 <code>/dubbo/com.foo.BarService/providers</code> 目录下写入自己的 URL 
地址</li>\n<li>服务消费者启动时: 订阅 <code>/dubbo/com [...]
   "link": "/zh-cn/docs/user/references/registry/zookeeper.html",
   "meta": {}
 }
\ No newline at end of file

Reply via email to